可能重复:
为什么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 ++ 11 main.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 ++ 11 main.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.
- 如果显式删除了移动构造函数,编译器是否应该使用复制构造函数?
- 有没有人知道“不可移动”类型的用途?
提前致谢。
A(A&&) = delete;
将其声明并定义为 delete
仍然宣布它,并不会使它完全不存在。相反,它是 类似 (但不完全相同)宣布它是空的和私人的。像这样:
private:
A(A&&){}
实际上,这是以前有时用于其他运营商的技巧 = delete
是可用的。
同样,它存在于查找的意义上,但调用它是不允许的,并且在C ++调用权限(几乎或所有情况下)都在其他所有事情之后完成,例如重载解析,名称查找。
标准实际上说(8.4.3)
删除的函数隐式内联。
并且注意到(我发现)说删除的函数不应该参与名称查找。
另外,从8.4.3开始
隐式或显式引用已删除函数的程序,
除了申报之外,还有不良形式。 [注意:这包括打电话
函数隐式或显式并形成指针或
指向函数的指针成员。它甚至适用于参考
没有潜在评估的表达式。
删除移动构造函数时,它不会从名称查找找到的函数集中删除它。每当您的代码通常使用移动构造函数时,您将收到错误,因为即使找到它,它也会被删除。
您的代码中有两个动作。第一个是你的时候 return a
因为当可以进行复制时,可以复制的对象由左值指定(a
,这里),它被视为一个举动。第二个是作业 A b = f()
因为一个 f()
给你一个尚未被引用约束的临时。
如果您希望找到复制构造函数而不是删除的移动构造函数,那么您应该删除已删除的定义。
这是一项研究任务,但我 认为 声明移动构造函数表明要考虑移动构造函数。什么时候得到 delete
d,这意味着如果有移动构造函数,可以将对象移动到可以移动的位置。如果你想要一个未被移动但被复制的对象,你只需要声明一个复制构造函数,你就不会提到移动构造函数。
我还没有在标准中找到声明,但是,它明确说明了上述内容,但在12.8 [class.copy]第9段中有注释支持上述声明:
[注意:当未隐式声明或显式提供移动构造函数时,否则将调用移动构造函数的表达式可能会调用复制构造函数。 - 尾注]
来自C ++ Working Draft 2012-11-02
8.4.3删除的定义[dcl.fct.def.delete]
...
2除了声明它之外,隐式或显式引用已删除函数的程序是不正确的。 [ 注意:这包括隐式或显式调用函数并形成指针或指向成员的指针
到功能。它甚至适用于未进行潜在评估的表达式中的引用。如果一个功能
重载,只有在通过重载决策选择函数时才会引用它。 - 结束说明]
...
4删除的函数是隐式内联的。
由于引用了已删除的移动构造函数,因此程序格式错误。
不可移动类型的“用法”可以是防止移动,因此防止返回本地对象。我自己没有见过这样的用法,我不知道这是否有意义,但是YMMV。