【问题标题】:Constructor access rules构造函数访问规则
【发布时间】:2009-05-19 10:28:09
【问题描述】:

如果我编译(在 G++ 下)并运行以下代码,它会打印“Foo::Foo(int)”。然而,在将复制构造函数和赋值运算符设为私有后,它无法编译并出现以下错误:“错误:‘Foo::Foo(const Foo&)’是私有的”。如果它只在运行时调用标准构造函数,它怎么需要一个复制构造函数?

#include <iostream>

using namespace std;

struct Foo {
    Foo(int x) {
        cout << __PRETTY_FUNCTION__ << endl;
    }


    Foo(const Foo& f) {
        cout << __PRETTY_FUNCTION__ << endl;
    }

    Foo& operator=(const Foo& f) {
        cout << __PRETTY_FUNCTION__ << endl;
        return *this;
    }
};

int main() {
    Foo f = Foo(3);
}

【问题讨论】:

    标签: c++ constructor


    【解决方案1】:

    这里使用了复制构造函数:

    Foo f = Foo(3);
    

    这相当于:

    Foo f( Foo(3) );
    

    其中第一组括号是对复制构造函数的调用。您可以通过以下方式避免这种情况:

    Foo f(3);
    

    请注意,编译器可能会选择优化复制构造函数调用,但复制构造函数必须仍然可用(即不是私有的)。 C++ 标准特别允许这种优化(参见第 12.8/15 节),无论复制构造函数的实现实际上做了什么。

    【讨论】:

    • 如果您声称它使用复制构造函数,为什么在输出中看不到它。原贴明确表示只调用了 ::Foo(int) 。
    • @Neil 但复制构造函数显然做了一些事情,所以编译器似乎不太可能优化它......
    • @Matthew:不。标准明确允许优化此类调用,因此编译器根本不关心任何副作用。任何称职的现代编译器都会优化这个调用。另一方面,该标准也明确规定调用必须仍然是可能的。因此,尼尔的解释是正确和中肯的。
    • @KIV, Matthew:Neil 和 Konrad 是对的,但不要做噩梦:编译器只允许在构造临时对象时优化掉 copy-ctor 调用。如果您明确请求副本,您的 copy-ctor 仍将被调用,例如用“Foo f(3);Foo g(f);”或“Foo f(3); Foo g = f;”。
    【解决方案2】:

    当编译器避免创建临时文件时,您看到的是标准优化允许的结果。即使存在副作用(例如您的示例中的 IO),编译器也可以用简单的构造替换构造和赋值。

    但是程序是否格式错误的事实不应该取决于情况,编译器何时进行此优化。这就是为什么

    Foo f = Foo(3);
    

    需要复制构造函数。和

    Foo f(3);
    

    没有。虽然它可能会导致相同的二进制代码。

    12.8.15 引述

    当满足某些条件时, 实现允许省略 类对象的复制构造, 即使复制构造函数和/或 对象的析构函数有边 效果。在这种情况下, 实施处理源和 省略复制操作的目标 只是两种不同的方式 指的是同一个对象,并且 该对象的破坏发生在 两者的后者 对象会被销毁 没有优化。111)这个 复制操作的省略是 以下允许 情况(可以结合 消除多个副本):

    ——在一个 函数中的 return 语句 类返回类型,当表达式 是非易失性的名称 具有相同的自动对象 cv-unqualified 类型作为函数 返回类型,复制操作可以 通过构造自动省略 对象直接进入函数 返回值

    ——当一个临时类 尚未绑定到 a 的对象 参考(12.2)将被复制到 具有相同的类对象 cv-不合格类型,副本 操作可以省略 构造临时对象 直接进入目标 省略复制

    另见“返回值优化”。

    【讨论】:

      猜你喜欢
      • 2023-04-02
      • 2021-04-17
      • 2021-09-04
      • 2021-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多