【问题标题】:Why is destructor called twice?为什么析构函数被调用两次?
【发布时间】:2021-11-06 21:32:54
【问题描述】:

我开始使用嵌套类,但我不确定我是否理解它们。我有以下代码:

#include <iostream>
#include <string>

class enclose
{
    private:
        int x;
    public:
        enclose(void);
        ~enclose(void);

        class nested1
        {
            public:
                nested1(void);
                ~nested1(void);
                void printnumber(enclose p);
        };

        nested1 nested;

};

enclose::enclose(void)
{
    std::cout << "Enclosed class constructor called" << std::endl;
    this->x = 10;
}

enclose::~enclose(void)
{
    std::cout << "Enclosed class destructor called" << std::endl;
}

enclose::nested1::nested1(void)
{
    std::cout << "Nested class constructor called" << std::endl;
}

enclose::nested1::~nested1(void)
{
    std::cout << "nested class destructor called" << std::endl;
}


void    enclose::nested1::printnumber(enclose p)
{
    std::cout << "the number is " << p.x << std::endl;
}

int main()
{
    enclose example;

    example.nested.printnumber(example);
}

我的代码输出如下:

Nested class constructor called
Enclosed class constructor called
the number is 10
Enclosed class destructor called
nested class destructor called
Enclosed class destructor called
nested class destructor called

如果构造函数只调用一次,如何调用两次析构函数?我以为你不能破坏以前没有建造的东西。

【问题讨论】:

  • printnumber 按值接受它的参数,在调用时会生成一个副本。该对象在函数结束时被销毁。
  • 你不会打印所有可能的方式来构造你的类,尤其是复制构造函数。
  • 这能回答你的问题吗? Why is the destructor of the class called twice?
  • 如果构造函数只被调用一次,怎么能调用两次析构函数?他们不能,尝试这样做是未定义的行为。提供的代码没有这样做。

标签: c++ nested destructor inner-classes


【解决方案1】:

因为您将example 的副本传递给enclose::nested1::printnumber(...)

也就是说,example.nested.printnumber(example) 通过值传递exampleexample 是一个类的实例,这意味着复制它。副本的析构函数也会触发。

printnumber的签名改成void enclose::nested1::printnumber(const enclose&amp; p),看看能不能得到你期望的结果。

【讨论】:

    【解决方案2】:

    为了获得更好的视图,进一步检测构造函数(包括复制构造函数)和析构函数以显示被调用对象的地址。

    然后,你会看到每个对象都被构造并最终被销毁,同时不同的个实例也被构造和销毁。

    例如

    enclose::enclose (const enclose& other)
    : x{other.x}
    {
        std::cout << "Enclosed class copy constructor called for instance "
            << this
            << '\n';
    }
    

    使用完全检测的类创建头文件会很有帮助,称为noisy 或类似名称。它没有数据成员,仅在创建、复制和销毁时用于输出。

    这很有用,因为它不需要在那些特殊成员中做任何真正的工作,并且您可以在任何您想要的类中重复使用它。您可以从enclosenested1 继承它,而无需重复您的工作。


    void printnumber(enclose p);
    通常,请记住通过引用传递复杂类型。所以你通常会将这个函数声明为void printnumber (const enclose&amp; p);


    顺便说一句:

    不要将(void) 写成()。这是 ANSI C 在获得 C++ 风格的函数声明时添加的内容,但仍需要支持旧方式。 Stroustrup 称其为“可憎之物”。

    不要为您的会员访问写this-&gt;。成员在范围内,不需要以任何方式限定。

    不要使用std::endl。当您需要换行符时,只需输出 \n

    【讨论】:

      猜你喜欢
      • 2013-12-11
      • 2011-02-07
      • 2017-11-03
      • 2013-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多