【问题标题】:Erasing container that holds a shared pointer also deletes the object that's being pointed to?擦除包含共享指针的容器也会删除指向的对象?
【发布时间】:2021-02-07 14:49:40
【问题描述】:

例如,使用原始指针:

Object *obPointer = new Object(); //dynamically allocating memory, meaning we have to delete it, ourselves, later

std::unordered_map<std::string, Objects*> objContainer; //container that holds a string key and a pointer to an object type.

objContainer.emplace("A", obPointer); // placing a string and a pointer to an object into the container. simple enough.

现在,如果我们删除该容器,它不会释放我们分配的内存,即“对象”类型。所以我们必须手动删除它,对吧?

delete obPointer;


objContainer.erase("A"); 

如果我们没有删除 obPointer,擦除容器是不够的 - 我们会发生内存泄漏。 无论如何,当谈到共享指针时,我不知道这是否有效,因为我们不会对它们调用 delete:

std::shared_ptr<Object> obPointer = std::make_shared<Object>(); //shared pointer

std::unordered_map<std::string, std::shared_ptr<Object>> container;

container.emplace("A", obPointer);

container.erase("A");

智能指针自己清理了吗?还是只有在超出范围时才会自行清理?

【问题讨论】:

  • 除非你有共享所有权,否则可能要使用std::unique_ptr
  • 当然它会“自行清理”。首先,这正是智能指针的用途。

标签: c++ pointers smart-pointers


【解决方案1】:

所以,就像 Dave 提到的,我应该使用唯一指针。在我的示例中,通过擦除容器,它不会释放由 shared_ptr 分配的内存。如果内存超出范围或引用,它只会删除内存。 因此,正如 Dave 所建议的,我使用 unique_pointer 来创建内存,然后我使用“std::move”将其“传递”给容器,这将所有权转移给容器的指针。因此,一旦我擦除该容器,内存就会释放。像这样:

//Container
std::unordered_map<std::string, std::unique_ptr<Object>> //container;
{//Scope just to demonstrate it works
 std::unique_ptr<Object> obPointer = std::make_unique<Object>(); //unique pointer

/*Now we transfer the ownership to the container, making its life spam
rely on the scope of the CONTAINER and the container itself*/
container.emplace("A", std::move(obPointer)); //std::move very important

}//only "obPointer" will die cuz of the scope, but it's null now. 
// the actual object that we created didn't delete itself. It's in the container



/*If we want to free up the memory, we should just erase the specific container
or wait for it to be out of the scope.*/
 container.erase("A"); //pointer deleted and memory freed

你去。一种“手动”删除智能指针的方法。很有用。

【讨论】:

    【解决方案2】:

    不管最后发生什么

    由于您有一个共享指针,它会跟踪它存在的副本数。在您的情况下,您的本地范围内有 obPointercontainer 内的一个对象(总共 2 个)。 调用erase 后,container 中的对象被破坏,计数返回 1。当obPointer 超出范围时,计数变为 0,QObject 实例被删除。

    【讨论】:

    • 那么,对象会一直停留在内存中,直到超出范围?这有点糟透了。有没有办法删除它?如果没有,我更喜欢在这种情况下使用原始指针。
    • 取决于您要执行的操作。但总的来说,您应该信任编译器优化器,而不是尝试手动优化您尚未确定为问题的东西。另外,如果您只想要容器中的对象,为什么要使用共享指针而不是唯一指针?
    • 我以为我不能传递唯一指针?我不能在容器中放置唯一指针,可以吗?
    • 您不能复制唯一的指针。如果您在容器中构造指针(通过 emplace)它可以工作,因为它只在一个地方。您也可以根本不使用动态分配,而只是将普通的QObjects 存储在那里。
    猜你喜欢
    • 1970-01-01
    • 2015-08-07
    • 2018-04-03
    • 1970-01-01
    • 2019-05-05
    • 2013-02-11
    • 2019-12-02
    • 2012-08-05
    相关资源
    最近更新 更多