【问题标题】:How can an object be destructed more times than it has been constructed?一个对象如何被破坏的次数比它被构造的次数多?
【发布时间】:2022-01-15 10:27:20
【问题描述】:

我有一个类,它的构造函数只被调用一次,但它的析构函数被调用了 3 次。

void test_body()
{
    std::cout << "----- Test Body -----" << "\n";

    System system1;

    Body body1({1,1,1}, {2,2,2}, 1, system1);

    system1.add_body(body1);

    std::cout << system1.get_bodies()[0].get_pos() << "\n";
}

body.hpp:

class Body {

private:
    Vec3D pos_;
    Vec3D vel_;
    double mass_{ 1 };
    System* system_{ nullptr };

public:

    /*#### Constructors ####*/

    Body() noexcept = default;

    Body(Vec3D pos, Vec3D vel, double mass, System& system):
    pos_(pos), vel_(vel), system_{&system}
    {
        if (mass <= 0)
            throw std::runtime_error("Mass cannot be negative.");
        mass_ = mass;

        std::cout << "Constructed Body" << "\n";
    }

    ~Body() {std::cout << "Destructed Body" << "\n";}


    /*#### Copy/Move ####*/

    Body(const Body &) =default;
    Body & operator=(const Body &) =default;
    Body(Body &&) =default;
    Body & operator=(Body &&) =default;

system.hpp:

class System {

private:
    std::vector<Body> bodies;

public:

    [[nodiscard]] inline
    std::vector<Body> get_bodies() const {return bodies;}

    inline
    void add_body(Body& body)
    {
        bodies.emplace_back(std::move(body));
    }
};

输出:

----- Test Body -----
Constructed Body
(1.000000, 1.000000, 1.000000)
Destructed Body
Destructed Body
Destructed Body

我知道这与 system1.add_body(body1);std::cout &lt;&lt; system1.get_bodies()[0].get_pos() &lt;&lt; "\n"; 有关,但问题是:

  • 如何破坏对象的次数多于构造次数?
  • 这是性能损失(我是否应该在更大范围内担心它)?如果是这样,我该如何解决?

PS:一般来说,我很乐意收到有关我的代码的建议!

【问题讨论】:

  • 您没有检测复制或移动构造函数。您根本没有检测到所有正在发生的构造。
  • 另外,还要将static_cast&lt;void const*&gt;(this) 写入输出,这样您就知道输出与哪个对象确切相关。
  • 回答标题中的问题,除非你的程序做了一些真正反常的事情(例如显式调用析构函数),否则对象只被构造一次,被销毁一次或根本不被销毁。跨度>
  • 一个对象如何被破坏的次数比它被构造的次数多? -- 它不能。为了向您证明这一点,请在输出中打印this 的值,而不仅仅是消息“Destructor Body”。和“构造体”。您会看到一些没有出现在“Constructed Body”中的地址,证明您没有检测到所有正在施工的地方。

标签: c++ class oop


【解决方案1】:

一个对象如何被破坏的次数比它被构造的次数多?

不能。您根本没有记录正在调用的每个构造函数。

例如,bodies.emplace_back(std::move(body)) 使用 Body(Body&amp;&amp;) 移动构造函数构造一个新的 Body 对象,该构造函数具有 default'ed 并且没有记录。

std::vector&lt;Body&gt; get_bodies() const 返回bodies副本,因此必须使用Body(const Body&amp;) 复制构造函数创建新的Body 对象,您也有default'ed 和没有记录。

尝试以下方法,您会更好地了解实际情况:

class Body
{
private:
    Vec3D pos_;
    Vec3D vel_;
    double mass_{ 1 };
    System* system_{ nullptr };

public:

    /*#### Constructors ####*/

    //Body() noexcept = default;
    Body() {
        std::cout << "Default Constructor " << static_cast<void*>(this) << "\n";
    }

    Body(Vec3D pos, Vec3D vel, double mass, System& system)
        : pos_(pos), vel_(vel), mass_(mass), system_(&system)
    {
        ...
        std::cout << "Conversion Constructor " << static_cast<void*>(this) << "\n";
    }

    ~Body() {
        std::cout << "Destructor " << static_cast<void*>(this) << "\n";
    }

    /*#### Copy/Move ####*/

    //Body(const Body &) = default;
    Body(const Body &src)
        : pos_(src.pos_), vel_(src.vel_), mass_(src.mass_), system_(src.system_)
    {
        ...
        std::cout << "Copy Constructor " << static_cast<void*>(this) << "\n";
    }

    //Body(Body &&) = default;
    Body(Body &&src)
        : pos_(std::move(src.pos_)), vel_(std::move(src.vel_)), mass_(src.mass_), system_(src.system_)
        ...
        src.mass_ = 0;
        src.system_ = nullptr;
        ...
        std::cout << "Move Constructor " << static_cast<void*>(this) << "\n";
    }

    //Body& operator=(const Body &) = default;
    Body& operator=(const Body &rhs) {
        if (&rhs != this) {
            pos_ = rhs.pos_;
            vel_ = rhs.vel_;
            mass_ = rhs.mass_;
            system_ = rhs.system_;
        }
        std::cout << "Copy Assignment " << static_cast<const void*>(&rhs) << " -> " static_cast<void*>(this) << "\n";
        return *this;
    }

    //Body& operator=(Body &&) = default;
    Body& operator=(Body &&rhs) {
        pos_ = std::move(rhs.pos_);
        vel_ = std::move(rhs.vel_);
        mass_ = rhs.mass_; rhs.mass_ = 0;
        system_ = rhs.system_; rhs.system_ = nullptr;
        std::cout << "Move Assignment " << static_cast<void*>(&rhs) << " -> " static_cast<void*>(this) << "\n";
        return *this;
    }

    ...
};

【讨论】:

    猜你喜欢
    • 2014-05-26
    • 2016-09-09
    • 2014-08-12
    • 2022-01-23
    • 2015-05-12
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多