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

function call ambiguity with pointer, reference and constant reference parameter

本文关键字:引用 常量 参数 歧义 函数调用 指针      更新时间:2023-10-16

我想做的是,允许使用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&版本。

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

没有歧义。 当重载集中有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的构造函数要求传递给它的指针是以 null 结尾的 c 字符串。 如果不是,则行为未定义。

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

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

所以0被当作NULL,并被解释为一个const char*,从中可以构造一个std::stringconst&能够延长左值的寿命,因此它可以传递到setS的重载中。