C++ 复制省略和右值
似乎复制省略的规则是参数必须是prvalue而不是xvalue,但为什么 似乎复制省略的规则是参数必须是prvalue而不是xvalue,但为什么 您的程序不包含可以执行复制/移动省略的情况。C++11标准在第12.8/31段中明确规定了这些情况: 当满足某些条件时,允许实现省略类的复制/移动构造 对象,即使为复制/移动操作选择了构造函数和/或为对象选择了析构函数 有副作用。[...] 在以下情况下,允许省略复制/移动操作,称为复制省略 可以组合使用以消除多个副本: -在具有类返回类型的函数中的return语句中,当表达式是 非易失性自动对象,而不是具有相同cv的函数或catch子句参数 类型作为函数返回类型,可以通过构造 自动对象直接输入函数的返回值 这不是您的情况,因为运算符返回的表达式=是*This,它不是具有自动存储持续时间的对象的名称。此外,您也不会存储operator=的结果 -在抛出表达式中,当操作数是非易失性自动对象的名称而不是 函数或catch子句参数,其范围不超出最内层 封闭try块(如果有)从操作数到异常的复制/移动操作 通过将自动对象直接构造到异常对象中,可以省略对象15.1 这不适用,因为您没有抛出表达式 -复制/移动未绑定到参考12.2的临时类对象时 对于具有相同cv类型的类对象,可以通过 将临时对象直接构造到省略的复制/移动的目标中 这也不适用,因为您没有临时值xvalue不是临时值 -当异常处理程序的异常声明第15条声明了相同类型的对象时 除了作为例外对象15.1的cv限定外,复制/移动操作可以省略 通过将异常声明视为异常对象的别名,如果程序的含义 将保持不变,除了为声明的对象执行构造函数和析构函数 异常声明 代码中没有异常处理程序,因此这种情况也不适用 如果你想问的问题是为什么事情是这样的,那么我无法提供客观、详尽的答案,尽管其他人可能会这样做。但我会尝试提出一些似是而非的论点 正如上面引用的标准的段落所规定的,在返回语句的情况下,复制省略意味着允许函数将要返回的对象直接构造到指定的对象中 具体地说,这意味着编译器可能会为该函数生成代码,该代码直接作用于要向其分配返回值的对象,并且位于被调用函数的堆栈帧之外,而不是在函数的堆栈帧内分配了自动存储持续时间的本地对象上。这意味着您可以将本地对象视为指定对象的别名 然而,这里有两个非常不同的对象,它们都是物质构造的,都需要内存,并且位于两个不同的地址。无法应用类似于前面所述的技巧,因为这种别名需要在程序执行期间更改对象的地址,这是非法的 似乎复制省略的规则是参数必须是prvalue而不是xvalue,但为什么 您的程序不包含可以执行复制/移动省略的情况。C++11标准在第12.8/31段中明确规定了这些情况: 当满足某些条件时,允许实现省略类的复制/移动构造 对象,即使为复制/移动操作选择了构造函数和/或为对象选择了析构函数 有副作用。[...] 在以下情况下,允许省略复制/移动操作,称为复制省略 可以组合使用以消除多个副本: -在具有类返回类型的函数中的return语句中,当表达式是 非易失性自动对象,而不是具有相同cv的函数或catch子句参数 类型作为函数返回类型, 复制/移动操作可以通过构造 自动对象直接输入函数的返回值 这不是您的情况,因为运算符返回的表达式=是*This,它不是具有自动存储持续时间的对象的名称。此外,您也不会存储operator=的结果 -在抛出表达式中,当操作数是非易失性自动对象的名称而不是 函数或catch子句参数,其范围不超出最内层 封闭try块(如果有)从操作数到异常的复制/移动操作 通过将自动对象直接构造到异常对象中,可以省略对象15.1 这不适用,因为您没有抛出表达式 -复制/移动未绑定到参考12.2的临时类对象时 对于具有相同cv类型的类对象,可以通过 将临时对象直接构造到省略的复制/移动的目标中 这也不适用,因为您没有临时值xvalue不是临时值 -当异常处理程序的异常声明第15条声明了相同类型的对象时 除了作为例外对象15.1的cv限定外,复制/移动操作可以省略 通过将异常声明视为异常对象的别名,如果程序的含义 将保持不变,除了为声明的对象执行构造函数和析构函数 异常声明 代码中没有异常处理程序,因此这种情况也不适用 如果你想问的问题是为什么事情是这样的,那么我无法提供客观、详尽的答案,尽管其他人可能会这样做。但我会尝试提出一些似是而非的论点 正如上面引用的标准的段落所规定的,在返回语句的情况下,复制省略意味着允许函数将要返回的对象直接构造到指定的对象中 具体地说,这意味着编译器可能会为该函数生成代码,该代码直接作用于要向其分配返回值的对象,并且位于被调用函数的堆栈帧之外,而不是在函数的堆栈帧内分配了自动存储持续时间的本地对象上。这意味着您可以将本地对象视为指定对象的别名 然而,这里有两个非常不同的对象,它们都是物质构造的,都需要内存,并且位于两个不同的地址。无法应用类似于前面所述的技巧,因为这种别名需要在程序执行期间更改对象的地址,这是非法的C++ 复制省略和右值,c++,c++11,C++,C++11,似乎复制省略的规则是参数必须是prvalue而不是xvalue,但为什么 似乎复制省略的规则是参数必须是prvalue而不是xvalue,但为什么 您的程序不包含可以执行复制/移动省略的情况。C++11标准在第12.8/31段中明确规定了这些情况: 当满足某些条件时,允许实现省略类的复制/移动构造 对象,即使为复制/移动操作选择了构造函数和/或为对象选择了析构函数 有副作用。[...] 在以下情况下,允许省略复制/移动操作,称为复制省略 可以组合使用以消除多个副本: -在具有类返回类型的函数中的
#include <string>
#include <iostream>
struct A
{
A (){}
A(const A&)
{
std::cout << "copy" << "\n";
}
A& operator =(A)
{
return *this;
}
};
int main()
{
A a;
A a2;
a=std::move(a2);
std::cin.ignore();
return 1;
}