C++ 为什么不调用复制构造函数将临时对象复制到新定义的对象 #包括 使用名称空间std; Y类{ 公众: Y(整数){ 库特
为什么? 因为在某些条件下(由C++11标准第12.8/31段规定),可以省略对复制构造函数或移动构造函数的调用,即使这些特殊函数(或析构函数)有副作用: 这种对复制/移动的省略 在以下情况下允许进行称为复制省略的操作 消除多个副本): -[……] -复制/移动未绑定到引用(12.2)的临时类对象时 对于具有相同cv类型的类对象,可以通过 将临时对象直接构造到省略的复制/移动的目标中 -[……] 这是所谓的“好像”规则的唯一例外,该规则通常限制编译器可以对程序执行的转换(优化)类型,以保持其可观察的行为 请注意,上面的机制称为复制省略-即使它实际上是对正在被省略的移动构造函数的调用。这被称为。C++ 为什么不调用复制构造函数将临时对象复制到新定义的对象 #包括 使用名称空间std; Y类{ 公众: Y(整数){ 库特,c++,visual-studio-2010,C++,Visual Studio 2010,为什么? 因为在某些条件下(由C++11标准第12.8/31段规定),可以省略对复制构造函数或移动构造函数的调用,即使这些特殊函数(或析构函数)有副作用: 这种对复制/移动的省略 在以下情况下允许进行称为复制省略的操作 消除多个副本): -[……] -复制/移动未绑定到引用(12.2)的临时类对象时 对于具有相同cv类型的类对象,可以通过 将临时对象直接构造到省略的复制/移动的目标中 -[……] 这是所谓的“好像”规则的唯一例外,该规则通常限制编译器可以对程序执行的转换(优化)类型,以保持其可观
Y(int)
是一个转换构造函数
不使用函数声明的单参数构造函数
显式说明符
编译器可以删除多余的副本并使用您的。这意味着
#include <iostream>
using namespace std;
class Y {
public:
Y(int ) {
cout << "Y(int)\n";
}
Y(const Y&) {
cout << " Y(const Y&)\n";
}
};
int main() {
Y obj1 = 2; // Line 1
}
相当于
Y obj1 = 2; // Line 1
这是因为构造函数只有一个参数,并且没有标记为
explicit
,因此编译器会自动转到:
Y obj1(2); // Line 1
进入:
要防止这种行为,请使用:
Y obj1(2);
显式Y(int){
explicit
导致编译器错误的事实是否意味着它不会神奇地将=2
转化为(2)
。explicit
所做的一切就是防止隐式转换为您的类型。“要防止这种行为[…],编译将在您的情况下失败。”请参阅Stefano的答案以进一步讨论(Andy的是正确的。)导致错误的显式表示它们决不是等价的。复制初始化并不等同于直接初始化。前者在概念上是通过从初始化表达式(2
)构造一个临时表达式来实现的,然后从该临时对象移动构造或复制构造obj1
。但是,编译器可以根据12.8/31删除对移动构造函数或复制构造函数的调用(参见我的答案)
Y obj1(2);
explicit Y(int ) {
cout << "Y(int)\n";
}