C++11 "Non-movable"型
C++11 "Non-movable" type
可能重复:
为什么C++11被删除的函数会参与过载解决?
关于以下C++11代码,我有两个问题:
#include <iostream>
using namespace std;
struct A {
A() { cout << "Default c-tor" << endl; }
A(const A&) { cout << "Copy c-tor" << endl; }
A(A&&) = delete;
};
A f()
{
A a;
return a;
}
int main()
{
A b = f();
return 0;
}
我用gcc和clang 得到了以下编译错误
gcc-4.7.2(g++--std=c++11main.cpp(:
main.cpp: In function ‘A f()’:
main.cpp:16:9: error: use of deleted function ‘A::A(A&&)’
main.cpp:8:2: error: declared here
main.cpp: In function ‘int main()’:
main.cpp:21:10: error: use of deleted function ‘A::A(A&&)’
main.cpp:8:2: error: declared here
clang-3.0(clang++--std=c++11main.cpp(:
main.cpp:19:4: error: call to deleted constructor of 'A'
A b = f();
^ ~~~
main.cpp:8:2: note: function has been explicitly marked deleted here
A(A&&) = delete;
^
1 error generated.
- 如果显式删除了move构造函数,编译器不应该使用copy构造函数吗
- 有人知道"不可移动"类型的用法吗
提前谢谢。
A(A&&) = delete;
声明并定义为delete
仍然声明它,并且不会使它完全不存在。相反,它与声明它为空和私有类似(但不完全相同(。像这样:
private:
A(A&&){}
事实上,在= delete
可用之前,这就是其他操作员有时使用的技巧。同样,它存在于查找的意义上,但调用它是不允许的,在C++中,调用权限(在几乎或所有情况下(是在其他一切之后完成的,例如重载解析、名称查找。
标准实际上说(8.4.3(
已删除的函数是隐式内联的。
还有一点(我发现(说,被删除的函数不应该参与名称查找。
此外,从8.4.3
一种隐式或显式引用已删除函数的程序,除了宣布它之外,它是不正规的。[注意:这包括打电话函数隐式或显式并形成指针或指向函数成员的指针。它甚至适用于可能未计算的表达式。
删除move构造函数时,它不会将其从通过名称查找找到的函数集中删除。每当您的代码正常使用move构造函数时,您都会收到一个错误,因为即使找到了它,它也已被删除。
你的代码中有两个动作。第一种是return a
,因为当复制省略是可能的,并且要复制的对象由左值(此处为a
(指定时,它被视为移动。第二个是分配A b = f()
,因为f()
为您提供了一个尚未绑定到引用的临时对象。
如果你想找到复制构造函数而不是删除的移动构造函数,你应该去掉删除的定义。
这是一项有点研究的任务,但我认为声明一个移动构造函数意味着要考虑该移动构造函数。当它得到delete
d时,这意味着如果有移动构造函数,对象可以移动到可以移动的地方。如果你想要一个没有被移动但被复制的对象,你只需要声明一个复制构造函数,而不会提到移动构造函数。
我还没有在标准中找到明确说明上述内容的声明,但在12.8[class.copy]第9段中有注释支持上述声明:
[注意:当移动构造函数没有隐式声明或显式提供时,原本会调用移动构造函数的表达式可能会调用复制构造函数。--end Note]
来自C++工作草案2012-11-02
8.4.3已删除定义[dcl.fct.def.delete]
…
2隐式或显式引用已删除函数而不是声明该函数的程序是格式错误的。注意:这包括隐式或显式调用函数,并形成指向成员的指针或指针到函数。它甚至适用于表达式中未潜在求值的引用。如果函数是重载的,只有通过重载解析选择了函数时才会引用它。——结束语]
…
4被删除的函数是隐式内联的。
由于引用了已删除的move构造函数,因此程序格式不正确。
不可移动类型的"用法"可以是防止移动,从而防止返回本地对象。我自己还没有见过这样的用法,我也不知道这是否有意义,但YMMV。
- MSVC是否支持C++11样式的属性而不是__declspec
- 创建LinkedList退出,返回代码为-11(SIGSEGV)
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 如何将模板转换为C++11之前的模板
- c++11评估顺序(未定义的行为)
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- C++中的VLA,扩展名为std=C++11
- 代码在我的计算机上运行良好,但是在将其提交给coursera时遇到未知的信号11问题
- "类模板示例<int>;"语句对 C++11 是什么意思?
- this_thread::sleep_for和计时时钟之间的关系是否由C++11标准指定
- 如何使用lock_guard在c++11中实现scoped_lock功能
- 使用 cmake 的 Linux 终端上的"Conversion to non-scalar type is requested"错误
- C++11 中不同类型的对象的 std::array 的替代方案
- 为什么 -mmacosx-version-min=10.10 不阻止使用标记为从 10.11 开始的函数?
- 为什么我的C++代码中出现'Segmentation Fault: 11'行?
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- STLPort using C++11
- C++11 "Non-movable"型