当我获得指向智能指针的指针时,是否必须释放内存?

时间:2015-11-23 02:10:01

标签: c++ c++11 smart-pointers

我正在学习新的c ++内容,而我目前正在学习使用智能指针(std::unique_ptr)。

假设我有std::vector std::unique_ptr。在我的代码中的某一点,我需要迭代这个stl向量并挑选出我需要计算的对象。

  for (const auto& obj : objectList)
  {
    if(/*check if this is an object I need*/)
      OtherFunc(obj.get());
  }

  void OtherFun(object* obj)
  {
     std::vector tempVector.push_back(obj);
  }

在OtherFunc中,我将作为参数传入的此对象添加到我保留并进行计算的另一个std::vector(表示为otherVector)。我不希望OtherFunc拥有对象的所有权。我只需要保留它们,所以我不必每帧传递对象。

我知道如果智能指针离开作用域(或者在我的情况下,退出程序),它们将自行解除分配,对包含智能指针对象的对象的otherVector会发生什么。我尝试在cplusplus.com查看文档,但我无法得到我的问题的答案。我是否必须取消分配我保存在otherVector中的所有对象?或者由于对象最初是智能指针,我可以假设otherVector中的所有指针也将变为null(因此,不会导致内存泄漏)。

3 个答案:

答案 0 :(得分:8)

Documentation for get()将声明它只返回一个指向托管资源的非所有者指针,而不是release(),它实际上将所有权转移到返回的指针。

这足以回答你的问题不应该清理指针。但是,还有其他一些需要注意的问题。

首先,您必须对生命周期持谨慎态度。管理资源仍然是智能指针的工作。如果智能指针清理,则原始指针将悬空。确保智能指针超过原始指针。如果你不能这样做,你应该使用shared_ptr,这可以确保只有在完成所有关联的智能指针后才清理资源。

现在有两种方法可以使用shared_ptr执行此任务。两者都需要将原始向量中的智能指针类型更改为shared_ptr。在前言中,假设您正在使用此指针并将其存储以供以后使用。当它被使用时,原始矢量可能会消失,其中的智能指针随之消失。我还假设您需要一个原始指针来执行您对资源执行的操作。也许您需要将它赋予C函数。

  1. 直接使用。如果您希望资源至少与OtherFun使用它所需的资源一样长,这是很好的。 OtherFun将采用shared_ptr,现在可以通过直接传递vector元素而不使用get来创建get

    事实上,在这里使用shared_ptr会导致错误,因为shared_ptr需要从另一个OtherFun构建,以便对资源进行适当的引用计数。 shared_ptrshared_ptr存储在任何需要的地方,并且存储的指针确保资源在原始向量时不会死亡。

    当有时间访问资源时,您可以从shared_ptr获取所需的原始指针,并确保本地weak_ptr比原始指针的使用寿命更长,这更容易而不是确保它比矢量元素更长。

  2. 存储OtherFun。如果您希望原始向量是唯一负责资源的向量,但是需要能够检查资源是否仍然有效并且如果是,则使用它。 weak_ptr会在任何需要的地方存储shared_ptr。如果原始矢量死亡,资源也会。

    当需要在其他地方使用资源时,使用weak_ptrlock获取shared_ptr(可能为空shared_ptr}或weak_ptrshared_ptr转换构造函数(抛出可能的异常)。您可以适当地检查资源是否仍然存在,get()确保它将保留在那里,直到您完成为止。此时,您可以继续选项1并获取所需的原始指针。

  3. 除此之外,您必须小心所有权。来自void OtherFun(object* obj) { std::unique_ptr<object> p(obj); } 的原始指针绝不能变成任何类型的所有者。例如,以下是错误,将导致指针的双重删除:

    *obj

    此处,您已punique_ptr拥有独特的所有权,即使您拨打的get() *obj仍然拥有shared_ptr::get()。这类似于前面提到的shared_ptr陷阱,您最终会有两个未关联的get()来管理相同的资源。

    release()本质上有些不安全并打破了封装。但是,为了实际使用智能指针,智能指针也是必要的。请注意,您可以陷入陷阱,无论是从获取原始指针的生命周期,还是最终将非拥有的原始指针转换为所有者。这就是res.write("{0}|{1}\n".format(line1.rstrip(), line2.rstrip())) 函数的用途。一般来说,当您不需要智能指针的原始指针以及仅将原始指针视为非所有者时,您会更加安全。

答案 1 :(得分:2)

您可以将另一个向量声明为std::vector<object*>。它将保存对象指针,但不会拥有它们,因此在释放自身时不会尝试释放对象。释放原始std::vector<std::unique_ptr<object>>时将释放对象。只需确保原始矢量比其他矢量更长。

答案 2 :(得分:2)

您可以使用指向std::unique_ptr内部的指针来“偷看”,但这对于智能指针是不可见的。如果唯一指针超出范围并删除其对象,则对其保持对象的任何普通指针都将变为无效。只要在唯一指针删除了对象后就不会使用常规指针,那么你是安全的,但是没有给出保护!

如果您需要多个指向具有不同生命周期的对象的指针,请考虑std::shared_ptr