一个对象如何被破坏的次数比它被构造的次数多?
How can an object be destructed more times than it has been constructed?
我有一个class,它的构造函数只被调用了一次,但它的析构函数被调用了三次。
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 << system1.get_bodies()[0].get_pos() << "\n";
有关,但问题是:
- 一个对象如何被破坏的次数比它被构造的次数多?
- 这是性能损失吗(我应该在更大范围内担心它)?如果是这样,我该如何解决?
PS:更一般地说,我很乐意收到有关我的代码的建议!
How can an object be destructed more times than it has been constructed ?
不能。您根本没有记录每个被调用的构造函数。
例如,bodies.emplace_back(std::move(body))
使用 Body(Body&&)
移动构造函数构造一个新的 Body
对象,您已经 default
编辑了它,但没有记录。
和 std::vector<Body> get_bodies() const
returns copy bodies
,因此必须使用 [= 创建新的 Body
对象18=] 复制构造函数,您同样也对其进行了 default
编辑,但未进行记录。
改为尝试以下操作,您将更清楚地了解实际情况:
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;
}
...
};
我有一个class,它的构造函数只被调用了一次,但它的析构函数被调用了三次。
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 << system1.get_bodies()[0].get_pos() << "\n";
有关,但问题是:
- 一个对象如何被破坏的次数比它被构造的次数多?
- 这是性能损失吗(我应该在更大范围内担心它)?如果是这样,我该如何解决?
PS:更一般地说,我很乐意收到有关我的代码的建议!
How can an object be destructed more times than it has been constructed ?
不能。您根本没有记录每个被调用的构造函数。
例如,bodies.emplace_back(std::move(body))
使用 Body(Body&&)
移动构造函数构造一个新的 Body
对象,您已经 default
编辑了它,但没有记录。
和 std::vector<Body> get_bodies() const
returns copy bodies
,因此必须使用 [= 创建新的 Body
对象18=] 复制构造函数,您同样也对其进行了 default
编辑,但未进行记录。
改为尝试以下操作,您将更清楚地了解实际情况:
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;
}
...
};