3

我想做的是,允许使用 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()

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

4

2 回答 2

3

没有歧义。当您A& setS(std::string* s)在重载集中时setS(0)调用指针版本并且0是空指针。这将是setS(nullptr).

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

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

于 2017-03-07T13:14:26.753 回答
0

当您删除setS函数的指针重载时,您调用const std::string&版本的原因是由于构造函数之一std::string

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

因此0被视为NULL,并解释为 a const char*,从中std::string可以构造 a 。能够延长左值的const&生命周期,因此它可以传递到 的重载中setS

于 2017-03-07T13:12:44.780 回答