Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.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++ 移动构造函数与复制省略。哪一个被叫?_C++_Move Semantics_Move Constructor_Copy Elision - Fatal编程技术网

C++ 移动构造函数与复制省略。哪一个被叫?

C++ 移动构造函数与复制省略。哪一个被叫?,c++,move-semantics,move-constructor,copy-elision,C++,Move Semantics,Move Constructor,Copy Elision,我这里有两段代码向您展示。它们是两个类,每个类都提供一个Move构造函数和一个返回临时值的函数 在第一种情况下,返回临时值的函数调用移动构造函数 在第二种情况下,返回临时值的函数只是告诉编译器执行复制省略 我很困惑:在这两种情况下,我都定义了一个Move构造函数和一个随机成员函数来返回一个临时值。但是行为改变了,我的问题是为什么 请注意,在下面的示例中,操作符复制省略是一种优化,现在每个现代编译器都提供了这种优化 在C++中返回巨大类对象时,该技术应用于…strong>但并非所有情况下都如此

我这里有两段代码向您展示。它们是两个类,每个类都提供一个Move构造函数和一个返回临时值的函数

  • 在第一种情况下,返回临时值的函数调用移动构造函数
  • 在第二种情况下,返回临时值的函数只是告诉编译器执行复制省略
我很困惑:在这两种情况下,我都定义了一个Move构造函数和一个随机成员函数来返回一个临时值。但是行为改变了,我的问题是为什么


请注意,在下面的示例中,操作符复制省略是一种优化,现在每个现代编译器都提供了这种优化

在C++中返回巨大类对象时,该技术应用于…strong>但并非所有情况下都如此

在第一个示例中,编译器执行移动构造函数,因为函数中有多个返回语句。

在的注释中,OP澄清了他在这里提出的问题:

我听说,即使存在多个副本,也会发生副本省略 返回语句。我想知道什么时候禁止抄袭

因此,我试图在这里解决这个问题:

在以下情况下允许复制/移动操作(称为C++删除拷贝):

  • 在具有类返回类型的函数中的
    return
    语句中,当表达式是具有自动存储持续时间(函数参数或处理程序异常声明引入的变量除外)的非易失性对象的名称,该对象的类型(忽略cv限定)与函数返回类型相同时,通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作

  • 在抛出表达式中,当操作数是一个非易失性自动对象(函数或catch子句参数除外)的名称,该对象的作用域不超出最里面的封闭try块(如果有)的末尾时,通过将自动对象直接构造到异常对象中,可以省略从操作数到异常对象的复制/移动操作

  • 当未绑定到引用的临时类对象将被复制/移动到具有相同类型的类对象(忽略cv限定)时,可以通过将临时对象直接构造到省略的复制/移动目标中来省略复制/移动操作

  • 当异常处理程序的异常声明声明与异常对象具有相同类型(cv限定除外)的对象时,如果程序的含义除了对异常声明所声明的对象执行构造函数和析构函数外,将保持不变,则可以通过将异常声明视为异常对象的别名来省略复制操作。不能从异常对象移动,因为它始终是左值

在所有其他情况下,禁止复制省略

函数中返回语句的数量与省略副本的合法性没有任何关系。然而,编译器被允许不执行复制省略,即使它是合法的,出于任何原因,包括返回语句的数量

C++17更新

现在有几个地方强制要求删除副本。如果prvalue可以直接绑定到by value函数参数、by value返回类型或命名的局部变量,则在C++17中必须使用复制省略。这意味着编译器甚至不必检查复制或移动构造函数。法律C++17:

struct X
{
    X() = default;
    X(const X&) = delete;
    X& operator=(const X&) = delete;
};

X
foo(X)
{
    return X{};
}

int
main()
{
    X x = foo(X{});
}

两位
operatorfriend std::ostream&OperatorTanks教授的签名是什么:)有没有办法让我的代码尽可能便携?一种独立于选择的方法compiler@gedamial:是的。不要在与复制/移动对象无关的特殊成员(复制/移动构造函数)中添加副作用(可能出于教育或调试目的除外)。这些副作用的例子有打印语句(如您的问题)或计数器(计算拷贝数或移动数)。如果您确实有这样的副作用,请确保您的程序的正确性不依赖于这些副作用,以便在发生复制省略时,您的程序的正确性不会受到不利影响。非常感谢先生。你太棒了
class Notemplate
{
   double d;
public:
   Notemplate(double val)
   {
      d = val;
   }

   Notemplate(Notemplate&& move)
   {
       cout << "Move Constructor" << endl;
   }

   Notemplate(const Notemplate& copy)
   {
       cout << "Copy" << endl;
   }

   Notemplate Redouble()
   {
       Notemplate example{ d*2 };
       return example;
   }
};

int main()
{
   Notemplate my{3.14};

   cout << my.Redouble();

   return 0;
}
struct X
{
    X() = default;
    X(const X&) = delete;
    X& operator=(const X&) = delete;
};

X
foo(X)
{
    return X{};
}

int
main()
{
    X x = foo(X{});
}