具有指针、引用和常量引用参数的函数调用歧义

function call ambiguity with pointer, reference and constant reference parameter

我想做的是,允许使用 setter 函数传递指针、引用或常量引用:

class A{
    std::string * p;
    std::string st;

    public:
    A():p(0)
    {}
    A& setS(const std::string& s){
        std::cout<<"called with const std::string&\n";
        st = s;
        p = &st;
        return *this;
    }
    A& setS(std::string& s) {
        std::cout<<"called with std::string&\n";
        p = &s;
        return *this; 
    }
    A& setS(std::string* s) {
        std::cout<<"called with std::string*\n";
        p = s;
        return *this; 
    }
};

int main(){
   std::string s;
   A a;
   a.setS(std::move(s)) //const std::string&
    .setS("")           //const std::string&
    .setS(s)            //std::string&
    .setS(0);           //std::string*
    //if std::string* version is not defined,
    //setS(0) calls the const std::string& version and throws exception 
    return 0;
}

但我已经看到,如果指针版本不存在,setS(0) 会调用 setS() 函数的 const std::string& 版本。

指针和参考版本之间或其他任何重要版本之间是否存在歧义?它是否定义明确并有望在所有编译器中以相同的方式工作?

当您删除 setS 函数的指针重载时,您调用 const std::string& 版本的原因是 one of the std::string constructors.

basic_string( const CharT* s,
              const Allocator& alloc = Allocator() );

因此 0 被视为 NULL,并被解释为 const char*,由此可以构造 std::stringconst& 能够延长左值的生命周期,因此可以将其传递到 setS.

的重载中

没有歧义。当重载集中有 A& setS(std::string* s) 时,setS(0) 调用指针版本,而 0 是空指针。它将等同于 setS(nullptr).

A& setS(std::string* s) 不在重载集中时,编译器会查看是否有办法从 0 构造一个临时字符串,然后将其传递给 A& setS(const std::string& s)因为 const& 可以绑定到临时文件。 std::string 可以从单个指针构造,并且 0 它再次被视为空指针。所以你得到了一个临时的空指针 std::string 传递给 const& 函数。

虽然这是未定义的行为。 std::string 的构造函数要求传递给它的指针是一个空终止的 c 字符串。如果不是,则行为未定义。