【问题标题】:Destructor call during object initialization?对象初始化期间的析构函数调用?
【发布时间】:2012-01-12 02:57:04
【问题描述】:

鉴于下面的代码,为什么我会收到关于 A 的析构函数是私有的错误?明明是私有的,但是我不明白为什么用这种方式初始化B的A对象实例会导致A的析构函数被调用。

对于任何拼写错误,我深表歉意,我正在从非网络系统的内存中重新创建代码,并且没有编译器。

class A
{
    public:
        A(int val) : x(val) {}

    private:
        int x;
        ~A() {}
};

class B
{
    public:
        B() : aInstance() {}

    private:
        A aInstance;
};

int main()
{
    B b;
}

【问题讨论】:

  • 不能对基于堆栈的对象执行此操作(即使是间接的)。这里对私有析构函数的使用和限制进行了很​​好的讨论:stackoverflow.com/questions/631783/…

标签: c++


【解决方案1】:

初始化本身不涉及使用 dtor,但B 的实例在main 的末尾被销毁。 B 包含一个A,所以当B 被销毁时,A 也必须被销毁——但A 的 dtor 不可用,因此执行此操作的代码可以不会生成。

【讨论】:

    【解决方案2】:

    由于B 类包含A 类的实例(作为私有字段aInstance),所以当B 的实例被销毁时,它必须被销毁。

    这正是您的main 内部发生的事情。 AsB b; 是在栈上分配和创建的,当函数结束时它会超出范围,必须销毁,就像 C++ 中的每个本地对象一样。

    【讨论】:

      【解决方案3】:

      原因是AB 的成员。 B 类型默认生成的构造函数必须是规则调用它的每个字段的析构函数。因此,这里有一个对 A 析构函数的隐式调用,它无法访问它,你会得到错误

      【讨论】:

        【解决方案4】:

        我怀疑 A 的析构函数是从构造函数中调用的。 A 的析构函数可能在 b 超出 main 范围时被调用(当程序终止时)。

        【讨论】:

          【解决方案5】:

          实际上是 B 需要访问析构函数而不是 main()。

          如果你让 B 成为 A 的朋友,它会起作用。如果您将main() 设为 A 的朋友,它将无法编译。

          因为 A 的实例被声明为“自动”,即它是一个类成员,所以它的删除不会发生在 B 的析构函数中,而是会发生在 B 的析构过程中。但是,这被认为是在 B 作为一个类的访问范围内。

          【讨论】:

            【解决方案6】:

            在main()结束时,当B超出作用域时,B应该如何释放类型A的成员?

            不能,因为您将析构函数声明为私有。

            【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-03-05
            • 2011-10-15
            • 2018-12-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多