如何解决共享指针的析构函数和擦除
据我所知,当从容器中擦除元素时会调用析构函数,如果我错了,请纠正我..但是 Destr X 打印不应该出现在 擦除之后
#include <iostream>
#include <memory>
#include <vector>
struct X
{
X()
{
std::cout<<"Contr X"<<std::endl;
}
~X()
{
std::cout<<"Destr X"<<std::endl;
}
};
using Xptr = std::shared_ptr<X>;
int main()
{
std::shared_ptr<X> x = std::make_shared<X>();
Xptr x2 = std::make_shared<X>();
std::vector<Xptr> v;
v.emplace_back(x);
v.emplace_back(x2);
v.erase(v.begin());
std::cout<<"after erase\n";
return 0;
}
解决方法
由于您使用了 shared_ptr
,因此您对这两个对象都有两个引用。它们是 x
和 x2
,以及向量 shared_ptr
内的 v
。
当你erase()
时,调用了shared_ptr
的析构函数,并且引用计数递减,但仍然是1
。因此对象 X
仍然存在。
离开main()
的范围后,计数再次递减。现在计数下降到零,并调用对象 X
的析构函数。
因此首先显示“擦除后”的输出,然后是“Destr X”。
当您将 x
和 x2
放入内部作用域时,您将看到预期的行为
std::vector<Xptr> v;
{
std::shared_ptr<X> x = std::make_shared<X>();
Xptr x2 = std::make_shared<X>();
v.emplace_back(x);
v.emplace_back(x2);
}
std::cout<<"before erase\n";
v.erase(v.begin());
std::cout<<"after erase\n";
现在你看到了
Contr X
Contr X
before erase
Destr X
after erase
Destr X
,
“据我所知,当从容器中删除元素时会调用析构函数......”
没错。但是当该元素是 std::shared_ptr
时,它是 std::shared_ptr
的析构函数被调用,而不是 std::shared_ptr
指向的任何析构函数。
std::shared_ptr
将仅调用它指向的对象的析构函数,如果它是最后 std::shared_ptr
指向它。但是在您的代码中,您有 2
std::shared_ptr
指向您创建的每个对象。 std::vector
中各有一个,本地 std::shared_ptr
变量 x
和 x2
各有一个,然后将它们添加到 std::vector
。
因此,当您从 std::vector
中删除元素时,std::vector
会删除它包含的 std::shared_ptr
,但是这些 std::shared_ptr
指向的对象不会被销毁,直到std::shared_ptr
变量 x
和 x2
在 main()
末尾超出范围。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。