【问题标题】:Is a defaulted move constructor considered user-declared?默认的移动构造函数是否被认为是用户声明的?
【发布时间】:2015-08-06 21:52:24
【问题描述】:

问题正如我的标题所述。

我之所以问,是因为我有一个带有默认移动构造函数的类,但尝试执行复制赋值的代码失败,说明复制赋值运算符已删除(根据 Visual Studio 2015)。

所以我检查了规则 here 中隐式声明的复制赋值运算符:

类 T 的隐式声明或默认的复制赋值运算符被定义为已删除,以下任何一项为真:

  • ...
  • T 有一个用户声明的移动构造函数
  • T 有一个用户声明的移动赋值运算符

所以基本上我不确定默认移动构造函数是否算作用户声明。我的直觉告诉我是的,但说到标准,我总是喜欢确定,因为假设可能代价高昂。

【问题讨论】:

  • 是的​​​​​​​​​​​​​​​​​​​​​
  • @Praetorian 足够公平。为什么VS2015会抱怨?当我删除我的默认移动构造函数时,代码编译得很好。
  • 大概您的类包含所有可复制分配的数据成员。当您删除用户声明的移动构造函数时,没有什么可以阻止复制赋值运算符的隐式声明
  • @0x499602D2 你可能需要 51540 rep ....
  • 这可能会有所帮助:stackoverflow.com/q/28963577/576911

标签: c++ c++11


【解决方案1】:

标准说:

12.8 复制和移动类对象 [class.copy]

如果类定义没有显式声明复制构造函数,则隐式声明。如果上课 定义声明了一个移动构造函数或移动赋值运算符,隐式声明的复制构造函数 被定义为删除;否则,它被定义为默认值(8.4)。如果该类具有后一种情况,则不推荐使用 用户声明的复制赋值运算符或用户声明的析构函数。

如果类定义没有显式声明复制赋值运算符,则隐式声明。如果 类定义声明了移动构造函数或移动赋值运算符,隐式声明的副本 赋值运算符被定义为删除;否则,它被定义为默认值(8.4)。如果类具有用户声明的复制构造函数或用户声明的析构函数,则不推荐使用后一种情况。

你的类有默认的移动构造函数,但它是显式声明的。 所以根据标准隐式声明的复制构造函数和复制赋值操作符被定义为删除。

8.4.2 显式默认函数 [dcl.fct.def.default]

显式默认函数和隐式声明函数统称为默认函数,实现应为它们提供隐式定义(12.1 12.4、12.8),这可能意味着将它们定义为已删除。如果函数是用户声明的并且在其第一次声明时没有显式默认或删除,则该函数是用户提供的。用户提供的显式默认函数(即,在其第一次声明后显式默认)是在显式默认的位置定义的。

使用此术语,您的移动构造函数是用户声明的,但不是用户提供的。

【讨论】:

  • 问题是关于复制assignment,而不是复制construction。我的类已经有一个默认的复制构造函数。
  • 赋值运算符也是如此。添加了关于它的引用。
【解决方案2】:

默认的特殊成员函数是用户声明的,但它也是由用户默认定义。该标准没有明确定义术语“用户声明”,但它本质上意味着必须由用户写出的任何特殊成员函数。所以下面声明了一个构造函数并将其定义为默认值。

struct X { 
    X() = default; // declaration and definition
};

将成员函数定义为默认意味着 定义 等同于隐式定义。它是用户声明的,因为它必须由用户输入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-15
    • 1970-01-01
    • 2012-07-19
    • 1970-01-01
    • 1970-01-01
    • 2020-05-08
    • 2014-07-05
    • 1970-01-01
    相关资源
    最近更新 更多