问题
What I am trying to do is, allow a pointer, reference or constant reference to be passed with the setter function:
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;
}
But I have seen that, if the pointer version is not there, the setS(0)
calls the const std::string&
version of the setS()
function.
Is there any ambiguity between the pointer and the reference versions or among any others that matter? Is it well defined and expected to work the same way in all compilers?
回答1:
There is no ambiguity. When you have A& setS(std::string* s)
in the overload set then setS(0)
calls the pointer version and 0
is a null pointer. It would be the equivelent of setS(nullptr)
.
When A& setS(std::string* s)
is not in the overload set then the compiler looks to see if there is a way it can construct a temporary string from 0
and then pass that to A& setS(const std::string& s)
since a const&
can bind to a temporary. std::string
can be constructed from a single pointer and again 0
it tread as a null pointer. So you get a temporary null pointer constructed std::string
passed to the const&
function.
This is undefined behavior though. The constructor for std::string
requires that the pointer passed to it be a null terminated c string. If it is not then the behavior is undefined.
回答2:
When you remove the pointer overload of your setS
function, the reason you are calling the const std::string&
version is because of one of the std::string constructors.
basic_string( const CharT* s,
const Allocator& alloc = Allocator() );
So 0
is being treated as NULL
, and interpreted as a const char*
, from which a std::string
can be constructed. The const&
is able to extend the lifetime of the lvalue so it may be passed into that overload of setS
.
来源:https://stackoverflow.com/questions/42649142/function-call-ambiguity-with-pointer-reference-and-constant-reference-parameter