首页 > 解决方案 > 将 nullptr 传递给我的重载函数会导致运行时错误

问题描述

为了了解更多使用指令和函数重载,我尝试了这个程序:

namespace ns{
    void f(int){cout << "int\n";}
    void f(double){cout << "double\n";}
    void f(std::string){cout << "string\n";}
    struct Foo{};
}

void f(ns::Foo const&){
    cout << "ns::Foo\n";
}

namespace bin{
    void f(int*){
        std::cout << "bin::f(int*)\n";
    }
}


int main(){

    using namespace ns;
    //using namespace bin;

    f(7); // int
    f(7.5); // double

    f(ns::Foo{}); // ns::Foo

    try{
        f(nullptr);
    }
    catch(std::exception const& e){
        std::cout << e.what() << std::endl;
    }
}

当我运行程序时,它工作正常,除了最后一次调用f(nullptr)导致运行时错误:

int
double
ns::Foo
basic_string::_M_construct null not valid

如果我取消注释usingnamespace 的指令bin,则代码可以正常工作。

using namespace bin;

输出:

int
double
ns::Foo
bin::f(int*)

标签: c++overloadingusing-directives

解决方案


using namespace bin;被注释掉时,只有 1 个f()可用版本可以将 anullptr作为输入。nullptr不能隐式转换为intor double,因此ns::f(int)ns::f(double)被排除。但是std::string可以从 a 构造const char*,并且nullptr可以隐式转换为const char*,因此编译器可以构造一个临时std::string对象来传递给ns::f(std::string)。但是,从 null构造 a是未定义的行为,因此会出现运行时错误(顺便说一句,这是不能保证的,因为行为是未定义的,所以任何事情都可能发生)。std::stringconst char*

如果using namespace bin;未注释掉,则有 2 个f()可用版本可以将 anullptr作为输入。 bin::f(int*)是比 更好的匹配ns::f(std::string),因为nullptr它可以隐式转换为int*,因此无需构造临时对象,因此编译器选择调用bin::f(int*)而不是ns::f(std::string).


推荐阅读