1

根据“内部 C++ 对象模型”,仅当以下四个条件中的至少一个为真时,编译器才会生成(如果程序员未声明)复制构造函数:

  1. 当类包含存在复制构造函数的类的成员对象时(由类设计器显式声明,如前面的 String 类的情况,或由编译器合成,如 Word 类的情况)

  2. 当类派生自存在复制构造函数的基类时(同样,显式声明或合成)

  3. 当类声明一个或多个虚函数时

  4. 当类派生自一个或多个基类是虚拟的继承链时

这意味着如果我有一个只有构造函数的类,那么编译器将不会提供复制构造函数。

举个例子:

class test
{
    test(){}
};
int main()
{
    test obj1;       //statement 1
    test obj2(obj1); //statement 2
}

上面的代码工作正常。现在问题来了,当我在类测试中添加以下行时:

test(const test& rhs) = delete;

"= delete" 确保不会自动提供复制构造函数。添加以上行后,我收到语句 2 的错误,其中Use of deleted function test::test(const test&).

我的问题是:根据“内部 C++ 对象模型”,我不需要上述类的复制构造函数,所以当我明确表示不生成复制构造函数(使用删除)时,为什么会出现错误?因为我期望编译器不需要上述类的复制构造函数。

我正在使用 gcc 版本 4.6.3。

4

3 回答 3

8

要使类可复制,它需要有一个复制构造函数。无论您是自己编写,还是编译器为您生成一个,都没有关系——它必须是可用的,test a; test b(a);才能成为有效的操作。

您显式地强制编译器删除复制构造函数——这是旧的“使复制构造函数私有”技巧的新版本。它不允许复制。所以不要对你不能复制感到惊讶。因为你告诉编译器不允许它。

于 2012-06-01T17:47:46.337 回答
2

隐式生成的复制构造函数的标准词是[class.copy]/7

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

[class.copy]/13

一个默认且未定义为已删除的复制/移动构造函数,如果它被 odr-used (3.2) 或在其第一次声明后显式默认,则被隐式定义。[注意:复制/移动构造函数是隐式定义的,即使实现省略了它的 odr-use (3.2, 12.2)。—尾注] 如果隐式定义的构造函数满足 constexpr 构造函数 (7.1.5) 的要求,则隐式定义的构造函数是 constexpr。

因此,仍然会为 生成一个复制构造函数test,并且它被语句 2 调用。我相信“内部 C++ 对象模型”正在谈论复制构造函数不是微不足道的时候。

于 2012-06-01T17:48:08.747 回答
0

这一行:

test obj2(obj1)

正在尝试调用复制构造函数。

于 2012-06-01T17:47:36.357 回答