谁能解释一下为什么类的destructor要调用 bar
在同类型对象被初始化的行中被调用?
#include <memory>
#include <iostream>
using namespace std;
class bar
{
public:
bar() {}
~bar() { std::cout << "destructor called " << std::endl; }
};
class foo
{
public:
foo(std::shared_ptr<bar> barP) {}
};
int main() {
std::shared_ptr<foo> f;
std::cout << "before init " << std::endl;
f = std::shared_ptr<foo>(new foo(std::shared_ptr<bar>(new bar())));
std::cout << "after init" << std::endl;
}
输出。
before init
destructor called
after init
这句话。
f = std::shared_ptr<foo>(new foo(std::shared_ptr<bar>(new bar())));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
构建一个临时的 shared_ptr
在语句结束时超出了范围。 这时 shared_ptr
消失,带走 bar
的副本(因为没有 shared_ptr
活着)。)
但如果你改变 foo
读成这样。
class foo
{
public:
foo(std::shared_ptr<bar> barP) { m_bar = barP; }
std::shared_ptr<bar> m_bar;
};
那么你得到的输出可能是你所期望的,因为... foo
保存一份《公约》的副本 shared_ptr
直到它(foo
)超出了范围,并且该副本保持 bar
活着。
before init
after init
destructor called
这是因为 bar
实例的生命力只与 foo
构造函数。 所以它被构造出来,传递到 shared_ptr
,然后进入 foo
构造函数。 一旦该构造函数完成(即使是在同一行),表达式本身就完成了,所以 shared_ptr
完成,并销毁。
在结束时 main
前面 cout
你还有一个 shared_ptr
归入 f
但未命名的 shared_ptr
对你的 bar
对象已经 "超出范围 "了。
首先,你不应该实例化的是 shared_ptr
这样一来 make_shared
来实例化 shared_ptr
. 请检查修改后的代码 -
#include <memory>
#include <iostream>
using namespace std;
class bar
{
public:
bar() {}
~bar() { std::cout << "destructor called " << std::endl; }
};
class foo
{
public:
foo(std::shared_ptr<bar> barP) {}
};
int main() {
std::shared_ptr<foo> f;
std::cout << "before init " << std::endl;
std::shared_ptr<bar> b = std::make_shared<bar>();
f = std::make_shared<foo>(b);
std::cout << "after init" << std::endl;
}
上述程序的输出 -
before init
after init
destructor called
一般来说,你的代码发生的情况是,你通过了 new bar
的构造者。foo
. 而且没有人持有所有权 bar
的共享指针,因此,ref计数变成了0,并且被删除了,因此被调用了destructor。所以,ref计数变成了0,它被删除了,因此被调用了destructor。
进一步阅读: make_shared vs new