C++ 什么';a=a(3)和a(3)之间的区别是什么?

C++ 什么';a=a(3)和a(3)之间的区别是什么?,c++,c++11,C++,C++11,假设我有: struct A { A(int x) : m_x(x) { } A(A&&) = delete; int m_x; } 以及: 为什么后者调用move构造函数?为什么这两条语句在生成的代码方面不同?为什么您希望两条代码路径相同 显然,在第二个示例中,您正在构造一个未命名的对象,分配a(auto a),然后从临时对象复制到a(这是一个移动,因为我们谈论的是临时对象)。编译器在这两种情况下生成相同的代码并不重要,因为在编译时需要定义必要的函数/

假设我有:

struct A
{
    A(int x) : m_x(x) { }
    A(A&&) = delete;
    int m_x;
}
以及:


为什么后者调用move构造函数?为什么这两条语句在生成的代码方面不同?

为什么您希望两条代码路径相同


显然,在第二个示例中,您正在构造一个未命名的对象,分配
a
auto a
),然后从临时对象复制到
a
(这是一个移动,因为我们谈论的是临时对象)。

编译器在这两种情况下生成相同的代码并不重要,因为在编译时需要定义必要的函数/构造函数。 这样想吧——编译/代码解析后会进行优化,但在这种情况下,最终代码将(应该)相同。

自动a=a(3)表示与
A A=A(3)相同
因为右侧的类型是
A

这正是它的意思:
A(3)
创建一个用
3
初始化的临时
A
,然后
A=
意味着:创建一个名为
A
A
作为初始值设定项

因此,创建一个临时文件,将其作为初始值设定项传递给
a
,然后临时文件被销毁。这种类型的初始化(使用
=
)称为复制初始化(尽管不要将其与“复制”混淆,它只是一个单词)

选择构造函数来构造接受
A
A
。这必须是副本或移动构造函数<代码>具有移动构造函数和复制构造函数。后者隐式生成并定义为deleted,因为有一个用户声明的move构造函数

被定义为已删除并不影响重载解析;在这种情况下,移动构造函数优先于复制构造函数

因此,您的代码试图调用
delete
d函数,该函数的格式不正确,因此会出现错误

请注意,如果未删除移动构造函数,则将应用复制省略。它在某些情况下起作用,其中一个变量由临时变量初始化,或者一个局部变量由值返回。规则是编译器可以对
a
和临时对象使用相同的内存,并且省略对复制/移动构造函数的调用

大多数/所有编译器实际上都会在这种情况下这样做。因此,您可以实际编写
autoa=a(3)并且在实践中不会得到任何不必要的移动。如果你为你的move构造函数写了一些输出的代码,你会发现没有输出任何东西


如果您想绝对确保没有不必要的副本,或者构造一个没有可用副本的对象,或者移动构造函数-停止编写指定不必要副本的代码<代码>A(3)
就足够了。

关于您的第一个评论,我的印象是,这通常被介绍为“这些都是相同的,除了通常不会出现的技术细节”。但也许我是在向OP兜售这些词。无论谁这样介绍它们,都应该因为不称职而被解雇。当意图明显相同时,为什么编译器会生成不同的代码?有没有一种情况下程序员会想要这种行为?你发现显而易见的是缺乏经验。使用移动构造函数的一个示例是用于写时复制逻辑,其中简单地将集合(例如字符串)分配给另一个集合不会立即复制整个集合,因为您可能实际上不想更改它。但是如果你真的改变了它,那就是复制发生的时候。@Blindy,如果行为是明显的,OP就不会问了。您还没有提供解释,只是居高临下。我想知道,在这种情况下,是否允许编译器省略移动,在删除移动构造函数的情况下?代码将被编译为相同的机器代码,并进行优化
A a(3); // Ok
auto a = A(3); // Error: function A(int&&) cannot be referenced - it's a deleted function