是否应该在赋值时调用构造函数?

bit*_*ise 25 c++

VS2015中以下代码的输出是"构造函数".

由于缺少赋值运算符,它不应该无法编译吗?

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;
}
Run Code Online (Sandbox Code Playgroud)

krz*_*zaq 30

是的,当有转换时,就像在您的测试用例中一样.

你有效地打电话了

b = B(a);
Run Code Online (Sandbox Code Playgroud)

因为隐式声明了B赋值运算符B& operator=(B const&),所以在重载解析期间会找到它.因为您的作业只是一次转换而不是匹配(这正是允许发生的转化次数),所以它转换aB然后将新的临时B转移给b.


Sam*_*hik 14

让我们考虑一个类似的例子.

double a;
int b=5;

a=b;
Run Code Online (Sandbox Code Playgroud)

你可以分配给a的唯一的东西double是另一个double.但是,一个int可以转换为double.

同样在这里,A可以转换为B,因为构造函数存在.这就是发生的事情.

  • 好吧,你可以将`int`分配给`double`.定义的行为是`int`被隐式转换为`double`,并且该转换的结果替换了`double`的存储值.也许最好说"可以存储在`double`变量中的唯一东西是'double`值",或者其他东西. (2认同)

hyd*_*yde 11

您的代码已隐式转换AB,b = a编译为b = B(a);.如果要将其检测为错误,可以使用说明explicit:

struct B {
    B(){}
    explicit B(const A& a) {
        std::cout << "constructor" << std::endl;
    }
};
Run Code Online (Sandbox Code Playgroud)

然后你应该得到错误,例如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&&'
Run Code Online (Sandbox Code Playgroud)

之后,永远不会隐式调用构造函数,如果要调用它,则必须明确地编写它: b = B(a);

  • 很好地提到`explicit`关键字 (3认同)