函数调用歧义与指针,引用和常量引用参数

时间:2017-03-07 13:06:41

标签: c++ pointers reference overload-resolution const-reference

我想要做的是,允许使用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)会调用const std::string&函数的setS()版本。

指针和参考版本之间是否存在任何歧义,或者其他任何重要问题之间是否存在歧义?它是否定义良好并且预期在所有编译器中以相同的方式工作?

2 个答案:

答案 0 :(得分:3)

没有歧义。如果在重载集中有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字符串。如果不是,则行为未定义。

答案 1 :(得分:0)

当您删除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的重载中。