Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么不调用复制构造函数将临时对象复制到新定义的对象 #包括 使用名称空间std; Y类{ 公众: Y(整数){ 库特_C++_Visual Studio 2010 - Fatal编程技术网

C++ 为什么不调用复制构造函数将临时对象复制到新定义的对象 #包括 使用名称空间std; Y类{ 公众: Y(整数){ 库特

C++ 为什么不调用复制构造函数将临时对象复制到新定义的对象 #包括 使用名称空间std; Y类{ 公众: Y(整数){ 库特,c++,visual-studio-2010,C++,Visual Studio 2010,为什么? 因为在某些条件下(由C++11标准第12.8/31段规定),可以省略对复制构造函数或移动构造函数的调用,即使这些特殊函数(或析构函数)有副作用: 这种对复制/移动的省略 在以下情况下允许进行称为复制省略的操作 消除多个副本): -[……] -复制/移动未绑定到引用(12.2)的临时类对象时 对于具有相同cv类型的类对象,可以通过 将临时对象直接构造到省略的复制/移动的目标中 -[……] 这是所谓的“好像”规则的唯一例外,该规则通常限制编译器可以对程序执行的转换(优化)类型,以保持其可观

为什么?

因为在某些条件下(由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";
}