如何从unique_ptr中删除原始指针

时间:2014-05-27 17:11:17

标签: c++ pointers unique-ptr delete-operator

我正在编写一个游戏框架,我有一个vector<unique_ptr<Object>>列表,我通过调用object.get()并将其发送出来,从该列表中分发指针。在此之前我发送引用而不是原始指针,但这导致了其他奇怪的问题所以我被告知这是更好的。但是,当我从列表中删除unique_ptr<Object>时,原始指针仍然存在。我也无法手动释放它们,我得到一个例外,说没有分配指针。

所以我的问题是:

  1. 如何从已删除的unique_ptr中删除原始指针?
  2. 也是一个更普遍的问题:

    1. 我是否在正确的轨道结构上传递指针而不是引用?
    2. PxlObject* PxlFramework::AddObject(PxlObject* obj)
      {
          std::unique_ptr<PxlObject> u_ptr(obj);
          objects_iterator = objects.insert(objects.end(), std::move(u_ptr));
          return obj;
      }
      
      void PxlFramework::DeleteObject(PxlObject* obj) {
          for(objects_iterator = objects.begin(); objects_iterator != objects.end(); ++objects_iterator)
          {
              if((*objects_iterator)->get_id() == obj->get_id())
              {
                  //attempting to delete the raw pointer here but it will result in an error
                  delete obj;
      
                  //removing the unique_ptr<PxlObject> from the list here
                  std::swap((*objects_iterator), objects.back());
                  objects.pop_back();
                  break;
              }
          }
      }
      

2 个答案:

答案 0 :(得分:2)

std::unique_ptr的重点是它“拥有”该对象,并在unique_ptr被销毁时自动管理删除。因此,您不应delete unique_ptrunique_ptr拥有的任何内容。为避免这种混淆,引用更为常见。此外,您有一种奇怪的感觉:AddObject会返回指向而非刚刚添加的PxlObject的指针。

这样的事情可能会更清洁一些:

template<class Us...>
PxlObject& PxlFramework::AddObject(Us&&... obj)
{
    std::unique_ptr<PxlObject> u_ptr(new PxlObject(std::forward<Us>(obj)...));
    objects_iterator = objects.insert(objects.end(), std::move(u_ptr));
    return **objects_iterator;
}

void PxlFramework::DeleteObject(PxlObject& obj) {
    auto finder = [](std::unique_ptr<PxlObject>& p)->bool 
            {return obj.get_id()==p->get_id();};
    auto it = find_if(objects.begin(), objects,end(), finder);
    if (it != objects.end())
        objects.erase(it);
    else
        throw ...;
}

答案 1 :(得分:0)

您不需要直接删除原始指针,而是可以使用vector.erase。这里有一个简单的例子:

#include <iostream>
#include <algorithm>
#include <memory>
#include <vector>

using namespace std;

typedef vector<unique_ptr<int>> ptr_list_t;

void remove_number(int x, ptr_list_t& ptr_list)
{
    for (ptr_list_t::iterator it = ptr_list.begin(); it != ptr_list.end(); ++it)
        if (*(it->get()) == x) {
            ptr_list.erase(it);     // Use vector.erase for deleting objects from a vector.
                                    // since it points to a unique_ptr, the object owned by it
                                    // will be destroyed automatically.
            break;
        }
}

int main()
{
    ptr_list_t ptr_list;

    // Generating the pointer to numbers. 0 - 9
    for (int i = 0; i < 10; i++)
        ptr_list.push_back(unique_ptr<int>(new int(i)));

    // Remove the number 3.
    remove_number(3, ptr_list);

    // Printing the list. The number 3 will not appear.
    for (ptr_list_t::iterator it = ptr_list.begin(); it != ptr_list.end(); ++it)
        cout << *(it->get()) << endl;

    return 0;
}

其他事情,我同意@MooingDuck:你不应该删除unique_ptr或者unique_ptr拥有的任何东西。但你确定可以。看看unique_ptr.release。此函数释放托管对象的所有权。