...撰文指出,拷贝构造函数总是被调用时,你有形式
myClass myVar = 24;
错误的声明。您的书是在C++ 11成为新标准之前编写的,所以它没有提到移动语义以及可能调用move-constructor的可能性。此外,它不会谈论copy-elision。是的,确实可以调用一个调用的复制构造函数,但由于称为copy-elison的优化,编译器允许从复制/移动构造函数中移除一个调用。这是允许的,即使它可能会影响程序的行为,但请注意,这不是保证每个编译器的情况发生。
如果你写一个program测试这个行为,你发现没有复制/移动构造函数被调用。通过命令行参数-fno-elide-constructors
disables这个省音,并允许从布展构造通话。
您正在使用被称为副本初始化初始化形式:
§8.5/15初始值设定
发生在形式的初始化
T x = a;
以及在 元传递,函数返回,抛出异常(15.1), 处理异常(15.3),和聚合成员初始化 (8.5.1)被称为复制初始化。 [注:复制初始化可以 调用移动(12.8)。 - 注完]
假设拷贝省音不会发生,编译器将构建类的临时实例,以转换为指定的类型。然后它将使用复制构造函数或移动构造函数从此临时对象复制或移动构造myVar
。移动构造函数优先于rval的拷贝构造函数,只有当你的类有一个可访问的移动构造函数时才会被调用;否则调用复制构造函数。
如果copy-elision没有发生,编译器将初始化myVar
,就好像它是从右侧复制构建的。这与as-if rule一致,其中声明编译器可以执行优化,因为它不会影响程序的可观察行为。
此外,他指出,当你有形式的声明
myClass myVar;
myVar = 24;
实际发生的事情是,myClass
构造函数整数作为参数调用创建的 一个无名临时变量类型myClass
,然后调用 赋值运算符。 [...]我的问题是这些说法是否仍然如此。
是的,构造函数参与隐式类型转换。从最新公布的草案,N3797:
§可以通过构造和 通过转换功能来指定类对象的12.3转换
类型转换。这些转换称为用户定义 转换和用于隐式类型转换(第4章),用于初始化 (8.5),并且对于显性类型转换(5.4,5.2.9)
你的作者给出的解释是正确的,除了移动赋值运算符将被调用,如果它是可访问的。
没有看到类定义是不可能的。 – juanchopanza 2014-10-07 20:42:21
如果'myClass'有一个移动构造函数和一个移动赋值操作符,那么将使用 – 2014-10-07 20:48:49
相关:[三是什么?](http://stackoverflow.com/questions/4172722/what-is-三个规则) – 2014-10-07 20:49:49