简体   繁体   中英

Should a constructor ever be called on assignment?

The output of the code below in VS2015 is "constructor".

Shouldn't it fail to compile due to the missing assignment operator?

struct A { };

struct B {
    B(){}
    B(const A& a) {
        cout << "constructor" << endl;
    }

    //B& operator=(const A& a) {
    //  cout << "assignment operator" << endl;
    //  return *this;
    //}
};

int main() {
    A a;
    B b;
    b = a;

    return 0;
}

Yes, when there is a conversion going on, like in your testcase.

You're effectively calling

b = B(a);

Because B 's assignment operator B& operator=(B const&) is implicitly declared, it is found during overload resolution. Because your assignment is only one conversion away from being a match (and that's exactly the number of conversions that are allowed to happen), it converts a to B and then assigns the new temporary B to b .

Let's consider an analogous example.

double a;
int b=5;

a=b;

The only thing you can assign to a double is another double . However, an int can be converted to a double .

Similarly here, A can be converted to B , because the constructor to do so exists. And that's what happens.

Your code has implicit conversion from A to B , the b = a is compiled as b = B(a); . If you want this to be detected as error, you can use the explicit specifier :

struct B {
    B(){}
    explicit B(const A& a) {
        std::cout << "constructor" << std::endl;
    }
};

Then you should get error, such as these generated by ideone.com :

prog.cpp: In function 'int main()':
prog.cpp:20:7: error: no match for 'operator=' (operand types are 'B' and 'A')
     b = a;
       ^
prog.cpp:5:8: note: candidate: B& B::operator=(const B&)
 struct B {
        ^
prog.cpp:5:8: note:   no known conversion for argument 1 from 'A' to 'const B&'
prog.cpp:5:8: note: candidate: B& B::operator=(B&&)
prog.cpp:5:8: note:   no known conversion for argument 1 from 'A' to 'B&&'

After that, the constructor will never be implicitly called, and if you want to call it, you have to write it explicitly: b = B(a);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM