C++11中删除成员函数的确切语义是什么?

ohfgkhjo  于 2022-12-27  发布在  其他
关注(0)|答案(2)|浏览(136)
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::运算符=(A &&)':试图引用已删除的函数
我只是想知道为什么当A& operator =(A&&)被删除时编译器不尝试A& operator =(const A&);
这种行为是由C
标准定义的吗?

carvr3hs

carvr3hs1#

a = A(); // error C2280

右边的表达式是临时的,这意味着它将查找operator=(A&&)并看到它被删除。因此出现错误。没有进一步的搜索。
=delete意味着“不要用我,而是用 * 下一个 * 最好的”,而是意味着“不要在你需要我的时候 * 用我--而是独自在野外”。
下面是另一个例子,如果我希望类X的示例只使用long创建,而 * 不使用其他类型 *(即使它转换为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部分之前 * 执行的-因此会导致错误,因为发现 selected 重载已删除。

ui7jx7zq

ui7jx7zq2#

当你=delete一个函数时,你实际上是在删除它的 * 定义 *。

8.4.3删除定义[dcl.fct.def.删除]

1以下形式的函数定义:

  • 属性说明符-seqopt声明符-seqopt声明符=删除;*

称为 * 删除的定义 *。具有删除的定义的函数也称为 * 删除的函数 *。
但是这样做的话,你也是在声明这个函数。引用标准[1]:
4被删除的函数是隐式内联的。[注意:单定义规则(3.2)适用于被删除的定义。-end note ]函数的被删除定义应该是函数的第一个声明[...]
因此,通过执行a = A(),编译器实际上解析为A::operator=(A&&),因为它已经被声明了(不是A::operator(const A&),因为A&&对r值“更有约束力”)。
2隐式或显式引用已删除函数的程序,而不是声明它,是格式不良的。
[1]这里强调的句子的语气实际上是命令式的。标准要求声明函数=delete d必须首先出现在它的其他声明之前。但它仍然支持删除函数也声明该函数的事实。

相关问题