C ++ 11中已删除函数的确切语义是什么?
struct A { A(); A(const A&); A& operator =(const A&); A(A&&) = delete; A& operator =(A&&) = delete; }; struct B { B(); B(const B&); B& operator =(const B&); }; int main() { A a; a = A(); // error C2280 B b; b = B(); // OK }
我的编译器是VC ++ 2013 RC。
错误C2280:'A&A :: operator =(A &&)':尝试引用已删除的函数
我只是想知道为什么编译器不会尝试A& operator =(const A&);
当A& operator =(A&&)
被删除?
这个行为是由C ++标准定义的吗?
a = A(); // error C2280
右边的expression式是一个临时的,这意味着它将查找operator=(A&&)
并且看到它被删除。 因此,错误。 没有进一步的search。
=delete
并不意味着“不要使用我,而是使用次最好的一个”。 它意味着,“ 当你需要我的时候不要使用我,而应该单独在野外。”
这是另一个例子。 如果我想让我的类X
的实例只用long
就可以创build,并且没有其他的types (即使它转换成long!),那么我将声明class X
:
struct X { X(long arg); //ONLY long - NO int, short, char, double, etc! template<typename T> X(T) = delete; }; X a(1); //error - 1 is int X b(1L); //ok - 1L is long
这意味着,在编译器看到=delete
部分之前执行重载parsing,因此会导致错误,因为所选的重载被删除。
希望有所帮助。
当你=delete
一个函数时,你实际上正在删除它的定义 。
8.4.3删除的定义[dcl.fct.def.delete]
1窗体的函数定义:
attribute-specifier-seqopt decl-specifier-seqopt declarator = delete;
被称为删除的定义 。 具有删除定义的function也被称为删除function 。
但是通过这样做,你也正在声明这个function。 引用标准[1] :
4删除的函数隐式内联。 [注意:单定义规则(3.2)适用于已删除的定义。 – 注意]function的删除定义应该是function的第一个声明 […]
因此,通过执行a = A()
,编译器实际上parsing为A::operator=(A&&)
因为它已被声明(不是A::operator(const A&)
,因为A&&
对r值“更具约束力” )。 但是,由于其定义被删除,该行是不合格的。
2除了声明外,隐式或显式引用已删除函数的程序是不合格的。
[1]这里强调句子的语气实际上是必要的。 该标准指示声明一个函数=delete
d必须先出现在其他声明之前。 但是,它还支持删除函数也声明函数的事实。