具有指针、引用和常量引用参数的函数调用歧义
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::string
。 const&
能够延长左值的生命周期,因此可以将其传递到 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 字符串。如果不是,则行为未定义。
我想做的是,允许使用 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::string
。 const&
能够延长左值的生命周期,因此可以将其传递到 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 字符串。如果不是,则行为未定义。