Class 析构函数的调用顺序与它们初始化时的预期顺序相反
Class Destructors not being called in the expected reverse order from which they were initialized in
我正在测试智能指针及其工作原理,然后我 运行 遇到了一个“问题”。这是我将要讨论的代码:
#include <iostream>
#include <memory>
class B; // forward declaration
class A {
private:
std::shared_ptr<B> b_ptr;
public:
void set_B(std::shared_ptr<B> &b) {
b_ptr = b;
std::cout << b_ptr.use_count() << std::endl;
}
A() { std::cout << "A Constructor" << std::endl; }
~A() { std::cout << "A Destructor" << std::endl; }
};
class B {
private:
std::weak_ptr<A> a_ptr;
public:
void set_A(std::shared_ptr<A> &a) {
a_ptr = a;
std::cout << a_ptr.use_count() << std::endl;
}
B() { std::cout << "B Constructor" << std::endl; }
~B() { std::cout << "B Destructor" << std::endl; }
};
int main() {
std::shared_ptr<A> a{std::make_shared<A>()};
std::shared_ptr<B> b{std::make_shared<B>()};
a->set_B(b);
b->set_A(a);
return 0;
}
这是 运行:
时的输出
A Constructor
B Constructor
2
1
A Destructor
B Destructor
现在我的问题是为什么析构函数在初始化时没有按相反的顺序被调用,例如(这是我期望的输出):
A Constructor
B Constructor
2
1
B Destructor
A Destructor
以上输出是我所期望的,但事实并非如此。我能想到的是:
- 变量
b
超出范围(如预期)
- 但它有两个强引用,所以
b
指向的动态分配对象没有被销毁,对象 b
本身作为 std::shared_ptr
对象被销毁,因此在动态分配的 B
类型对象 上只留下 1 个强引用
- 变量
a
在上述事件后超出范围,并且由于 std::weak_ptr
不影响 std::share_ptr
的 [,它反过来只有 1 个强引用=41=],这意味着动态分配的 A
类型对象被破坏了......但这就是我想知道 B 析构函数是如何在 A 析构函数之后被调用的地方它对我来说没有任何意义
A 拥有对 B 的引用。
您的 main
范围拥有对 A
和 B
的引用。当 main
结束时,它会删除 B
引用,然后是 A
.
B
引用将引用计数减为 1。A
减为 0。然后运行 A
s 析构函数。
析构函数体运行后,每个成员都被销毁。 A
对 B
的引用消失了。 B
s 析构函数被调用。
因此您看到的顺序。
我正在测试智能指针及其工作原理,然后我 运行 遇到了一个“问题”。这是我将要讨论的代码:
#include <iostream>
#include <memory>
class B; // forward declaration
class A {
private:
std::shared_ptr<B> b_ptr;
public:
void set_B(std::shared_ptr<B> &b) {
b_ptr = b;
std::cout << b_ptr.use_count() << std::endl;
}
A() { std::cout << "A Constructor" << std::endl; }
~A() { std::cout << "A Destructor" << std::endl; }
};
class B {
private:
std::weak_ptr<A> a_ptr;
public:
void set_A(std::shared_ptr<A> &a) {
a_ptr = a;
std::cout << a_ptr.use_count() << std::endl;
}
B() { std::cout << "B Constructor" << std::endl; }
~B() { std::cout << "B Destructor" << std::endl; }
};
int main() {
std::shared_ptr<A> a{std::make_shared<A>()};
std::shared_ptr<B> b{std::make_shared<B>()};
a->set_B(b);
b->set_A(a);
return 0;
}
这是 运行:
时的输出A Constructor
B Constructor
2
1
A Destructor
B Destructor
现在我的问题是为什么析构函数在初始化时没有按相反的顺序被调用,例如(这是我期望的输出):
A Constructor
B Constructor
2
1
B Destructor
A Destructor
以上输出是我所期望的,但事实并非如此。我能想到的是:
- 变量
b
超出范围(如预期) - 但它有两个强引用,所以
b
指向的动态分配对象没有被销毁,对象b
本身作为std::shared_ptr
对象被销毁,因此在动态分配的B
类型对象 上只留下 1 个强引用
- 变量
a
在上述事件后超出范围,并且由于std::weak_ptr
不影响std::share_ptr
的 [,它反过来只有 1 个强引用=41=],这意味着动态分配的A
类型对象被破坏了......但这就是我想知道 B 析构函数是如何在 A 析构函数之后被调用的地方它对我来说没有任何意义
A 拥有对 B 的引用。
您的 main
范围拥有对 A
和 B
的引用。当 main
结束时,它会删除 B
引用,然后是 A
.
B
引用将引用计数减为 1。A
减为 0。然后运行 A
s 析构函数。
析构函数体运行后,每个成员都被销毁。 A
对 B
的引用消失了。 B
s 析构函数被调用。
因此您看到的顺序。