我创建了一个类Animal:
class Animal {\npublic:\n Animal() = default;\n Animal(Animal&& a) = delete;\n Animal(Animal& a) = delete;\n\n Animal& operator=(Animal&& a) = delete;\n Animal& operator=(Animal& a) = delete;\n};\n\nAnimal func1() {\n return Animal();\n}\n\nAnimal func2() {\n Animal a {};\n return a;\n}\n\nint main(void) {\n Animal a1 = func1();\n Animal a2 = func2();\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n我不明白为什么func1()工作正常:return Animal()创建一个右值对象,然后a1在函数中使用该对象进行初始化main;据我所知,它等于
Animal a1 = func1()\n ==\nAnimal a1 = Animal&& temp //(I wrote type in assignment for clarifying)\nRun Code Online (Sandbox Code Playgroud)\n我读到返回值是右值;但是,func2我收到错误 \xe2\x80\x98copy 构造函数被删除\xe2\x80\x99 而不是移动构造函数,为什么?
这里我们考虑一下这样的说法:
\n Animal a1 = func1();\nRun Code Online (Sandbox Code Playgroud)\n调用表达式func1()是类型为 的rvlalueAnimal。而从 C++17 开始,由于强制复制 elison:
\n\n在以下情况下,编译器需要省略类对象的复制和移动构造,即使复制/移动构造函数和析构函数具有可观察到的副作用。这些对象直接构造到存储中,否则它们将被复制/移动到存储中。复制/移动构造函数不需要存在或可访问:
\n
\n\n\n
\n- 在 return 语句中,当操作数是与函数返回类型相同的类类型(忽略 cv 限定)的纯右值时:
\n
也就是说,对象直接构造到存储中,否则它们将被复制/移动到存储中。也就是说,在这种情况下(对于 C++17),不需要可用的复制/移动构造函数。所以这个声明是有效的。
\n这里我们考虑一下这样的说法:
\nAnimal a2 = func2();\nRun Code Online (Sandbox Code Playgroud)\n来自非强制性副本埃利森,
\n\n\n在以下情况下,允许但不要求编译器省略类对象的复制和移动 (C++11 起) 构造,即使复制/移动 (C++11 起) 构造函数和析构函数具有可观察端-效果。这些对象直接构造到存储中,否则它们将被复制/移动到存储中。这是一种优化:即使发生并且未调用复制/移动 (C++11 起) 构造函数,它仍然必须存在且可访问(就好像根本没有发生优化一样),否则程序会出错-形成:
\n
\n\n\n
\n- 在 return 语句中,当操作数是具有自动存储持续时间的非易失性对象的名称时,该对象不是函数参数或 catch 子句参数,并且与以下对象具有相同的类类型(忽略 cv 限定):函数返回类型。
\n
也就是说,复制/移动构造函数必须存在(即这些构造函数必须存在且可访问),但由于您已明确将它们标记为已删除,因此该语句失败并出现错误:
\nerror: use of deleted function \xe2\x80\x98Animal::Animal(Animal&&)\xe2\x80\x99\nRun Code Online (Sandbox Code Playgroud)\n错误也可以在这里看到
\n| 归档时间: |
|
| 查看次数: |
582 次 |
| 最近记录: |