智能指针的计数器递减如何工作?
How does counter decrement of smart pointer work?
下面是共享指针的示例代码。我在花括号范围内定义了一个共享指针。 sp1 由 new A(计数器 = 1)初始化,并将 sp1 分配给 sp2(复制 and/or 分配将计数器增加 1,因此,计数器 = 2)。我一直认为当计数器变为 0 时会调用 A 的析构函数。但在我的例子中,智能指针即将超出范围(通过大括号)时,计数器为二。
我的问题是:谁将计数器从 2 更改为 0?
#include <iostream>
#include <memory>
using namespace std;
class A{
public:
~A(){
std::cout << "~A" << std::endl;
}
};
int main(){
{
shared_ptr<A> sp1 (new A);
shared_ptr<A> sp2 = sp1;
std::cout << "sp1 count = " << sp1.use_count() << std::endl;
std::cout << "sp2 count = " << sp2.use_count() << std::endl;
}
return 0;
}
编辑:
Link 发表在 smart pointer
输出:
sp1 count = 2
sp2 count = 2
~A
当您的代码到达 main 的末尾时,sp1
和 sp2
的析构函数都会运行,这会将计数器递减为零 - 这是共享指针的一个非常重要的部分,即析构函数减少了引用计数,因此,当 "nothing" 剩余时,将调用实际共享对象的析构函数。
shared_ptr
的析构函数会有这样的逻辑:
counter--; // Should be atomic!
if (counter == 0)
{
delete owned_thing;
}
一个更好的例子 (IMO) 应该是这样的:
int main()
{
std::shared_ptr<A> sp1{new A};
std::cout << "1: sp1.use_count() = " << sp1.use_count() << '\n';
{
std::shared_ptr<A> sp2 = sp1;
std::cout << "2: sp1.use_count() = " << sp1.use_count() << '\n';
std::cout << "2: sp2.use_count() = " << sp2.use_count() << '\n';
}
std::cout << "3: sp1.use_count() = " << sp1.use_count() << '\n';
}
这个程序的输出应该是(使用你的 class 及其析构函数):
1: sp1.use_count() = 1
2: sp1.use_count() = 2
2: sp2.use_count() = 2
3: sp1.use_count() = 1
~A
首先你创建一个共享指针并初始化它,使使用计数器1
。然后你进入一个新的范围,并在其中创建一个新的共享指针,用旧指针初始化它(使用共享指针复制构造函数),导致两个指针的使用计数为 2
。然后第二个共享指针超出范围,共享指针析构函数将使用计数减一。最后,第二个共享指针超出范围,如 main
函数 returns,并且使用计数由 sp1
析构函数递减。现在它已经达到零,并且包含的指针被删除导致 A
析构函数被调用。
下面是共享指针的示例代码。我在花括号范围内定义了一个共享指针。 sp1 由 new A(计数器 = 1)初始化,并将 sp1 分配给 sp2(复制 and/or 分配将计数器增加 1,因此,计数器 = 2)。我一直认为当计数器变为 0 时会调用 A 的析构函数。但在我的例子中,智能指针即将超出范围(通过大括号)时,计数器为二。
我的问题是:谁将计数器从 2 更改为 0?
#include <iostream>
#include <memory>
using namespace std;
class A{
public:
~A(){
std::cout << "~A" << std::endl;
}
};
int main(){
{
shared_ptr<A> sp1 (new A);
shared_ptr<A> sp2 = sp1;
std::cout << "sp1 count = " << sp1.use_count() << std::endl;
std::cout << "sp2 count = " << sp2.use_count() << std::endl;
}
return 0;
}
编辑: Link 发表在 smart pointer
输出:
sp1 count = 2
sp2 count = 2
~A
当您的代码到达 main 的末尾时,sp1
和 sp2
的析构函数都会运行,这会将计数器递减为零 - 这是共享指针的一个非常重要的部分,即析构函数减少了引用计数,因此,当 "nothing" 剩余时,将调用实际共享对象的析构函数。
shared_ptr
的析构函数会有这样的逻辑:
counter--; // Should be atomic!
if (counter == 0)
{
delete owned_thing;
}
一个更好的例子 (IMO) 应该是这样的:
int main()
{
std::shared_ptr<A> sp1{new A};
std::cout << "1: sp1.use_count() = " << sp1.use_count() << '\n';
{
std::shared_ptr<A> sp2 = sp1;
std::cout << "2: sp1.use_count() = " << sp1.use_count() << '\n';
std::cout << "2: sp2.use_count() = " << sp2.use_count() << '\n';
}
std::cout << "3: sp1.use_count() = " << sp1.use_count() << '\n';
}
这个程序的输出应该是(使用你的 class 及其析构函数):
1: sp1.use_count() = 1 2: sp1.use_count() = 2 2: sp2.use_count() = 2 3: sp1.use_count() = 1 ~A
首先你创建一个共享指针并初始化它,使使用计数器1
。然后你进入一个新的范围,并在其中创建一个新的共享指针,用旧指针初始化它(使用共享指针复制构造函数),导致两个指针的使用计数为 2
。然后第二个共享指针超出范围,共享指针析构函数将使用计数减一。最后,第二个共享指针超出范围,如 main
函数 returns,并且使用计数由 sp1
析构函数递减。现在它已经达到零,并且包含的指针被删除导致 A
析构函数被调用。