function call ambiguity with pointer, reference and constant reference parameter

懵懂的女人 提交于 2019-12-22 10:45:49

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!