我正在学习Accelerated C ++中的自动转换,作者声明当你有一个表单声明时总是调用复制构造函数
myClass myVar = 24;
另外,他说当你有表格的陈述时
myClass myVar;
myVar = 24;
实际发生的是调用以整数作为参数的myClass构造函数来创建myClass类型的未命名临时变量,然后调用赋值运算符。我相信这本书写于2000年。我的问题是这些说法是否仍然属实。我了解了移动构造函数并将赋值操作移动到其他地方,我想知道是否调用了这些操作而不是赋值操作符/复制构造函数。
感谢您的时间。对此,我真的非常感激。
答案 0 :(得分:2)
...作者声明,当你有一个表单声明
时,总是会调用复制构造函数myClass myVar = 24;
<强>错误强>
你的书是在C ++ 11成为新标准之前编写的,所以它没有提到移动语义和可能会调用 move-constructor 的可能性。而且,它没有谈论 copy-elision 。是的,确实可以调用调用的复制构造函数,但由于名为copy-elison的优化,允许编译器从复制/移动构造函数中删除调用。这是允许的,即使它可能会影响程序的行为,但请注意,这不是保证在每个编译器上发生。
如果您编写program来测试此行为,则会发现没有调用复制/移动构造函数。传递命令行参数-fno-elide-constructors
disables此省略并允许来自 move-constructor 的调用。
您正在使用的初始化形式称为复制初始化:
§8.5/ 15初始化程序
以
形式出现的初始化T x = a;
以及 参数传递,函数返回,抛出异常(15.1), 处理异常(15.3),并聚合成员初始化 (8.5.1)称为复制初始化。 [注意:复制初始化可能 调用移动(12.8)。 - 结束说明]
假设没有发生copy-elision,编译器将构造一个类的临时实例,以便转换为指定的类型。然后,它将使用copy-constructor或move-constructor从此临时文件复制或移动构造myVar
。移动构造函数优先于rvalues的复制构造函数,并且只有在类具有可访问的移动构造函数时才会调用它。否则调用复制构造函数。
如果没有发生copy-elision,编译器将初始化myVar
,就像它是从右侧复制构造一样。这符合as-if rule,它指出编译器可以执行优化,因为它不会影响程序的可观察行为。
另外,他说当你有表格的陈述时
myClass myVar; myVar = 24;
实际发生的是
myClass
将整数作为参数的构造函数调用以创建 一个myClass
类型的未命名临时变量,然后是 赋值运算符被调用。 [...]我的问题是这些说法是否仍然存在。
是的,构造函数确实参与了隐式类型转换。从最新草稿N3797:
开始§12.3转化次数
类对象的类型转换可以由构造函数和指定 通过转换功能。这些转换称为用户定义 转换并用于隐式类型转换(第4条) 初始化(8.5),以及显式类型转换(5.4,5.2.9)
作者对该部分的解释是正确的,除非移动赋值运算符在可访问时将被调用。