【问题标题】:Destructor and erase for shared pointers共享指针的析构函数和擦除
【发布时间】:2023-03-11 15:02:01
【问题描述】:

据我所知,从容器中删除元素时会调用析构函数,如果我错了,请纠正我。但是 Destr X 打印不应出现在 after 删除之前

#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 仍然有一个所有者(即x)。共享对象在其所有所有者都对其失去兴趣之前不会被销毁。
  • 你是对的。 Xptr 被破坏v.erase(v.begin());。 Xptr 析构函数说“哦,X 上还有另一个活 Xptr,所以不会在这里破坏它。一切都完成了,再见。”
  • Destr X 打印不应出现在擦除后”之前。你是对的,他们不应该,他们don't。你有什么问题?

标签: c++ c++11 c++14


【解决方案1】:

由于您使用shared_ptr,因此您对这两个对象都有两个引用。它们是xx2,以及shared_ptrs 内的向量v

当你erase()时,shared_ptr的析构函数被调用,引用计数递减,但还是1。因此对象X 仍然存在。 离开main() 的范围后,计数再次递减。现在计数归零,对象X的析构函数被调用。

因此首先显示输出“擦除后”,然后才显示“Destr X”。


当您将 xx2 放入内部范围时,您将看到预期的行为

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

【讨论】:

    【解决方案2】:

    “据我所知,当从容器中删除元素时会调用析构函数...”

    没错。但是,当该元素是 std::shared_ptr 时,它是调用其析构函数的 std::shared_ptr,而不是 std::shared_ptr 指向的任何析构函数。

    std::shared_ptr调用它所指向的对象的析构函数,如果它是 最后一个std::shared_ptr 指向它。但是在您的代码中,您有 2 std::shared_ptrs 指向您创建的每个对象。 std::vector 中各有一个,std::shared_ptr 本地变量 xx2 在添加到 std::vector 之前各有一个。

    因此,当您从std::vector 中删除元素时,std::vector 会删除其中包含的std::shared_ptrs,但那些std::shared_ptrs 指向的对象直到std::shared_ptr 变量xx2main() 末尾超出范围。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-27
      • 2018-08-13
      • 2019-05-05
      • 2021-11-28
      • 1970-01-01
      • 2018-02-11
      • 2021-02-07
      • 1970-01-01
      相关资源
      最近更新 更多