使用iterator ptr更新unique_ptr的向量

时间:2014-03-25 23:27:23

标签: c++ c++11 stl eclipse-cdt

代码如下:

#include "MyObject.h"
#include <vector>
#include <memory>

class MyCollection {
private:
    std::vector<std::unique_ptr<MyObject*>> collection;
public:
    MyCollection();
    virtual ~MyCollection();

    int insert(MyObject* newValue);

};

int MyCollection::insert(MyObject* newValue) {
    if (collection.empty()) {
        collection.push_back(move(make_unique<MyObject*>(newValue)));
        return 0;
    }
    int index = collection.size()-1;

    collection.resize(collection.size()+1);
    vector<unique_ptr<MyObject*>>::reverse_iterator pos = collection.rbegin();

    for ( ; (index >= 0) && (pos+1) != collection.rend() && stringToUpper((*(pos+1)->get())->getObjectName()) > stringToUpper(newValue->getObjectName()); ++pos) {
        pos = (pos+1);
        index--;
    }

    pos = ?newValue; // How do I do this?
        //pos->reset(move(make_unique<MyObject*>(newValue)));

    return index+1;
}

make_unique()实现取自http://scrupulousabstractions.tumblr.com/post/37576903218/cpp11style-no-new-delete

我的问题是有没有办法做我正在尝试分配到reverse_iterator(pos = newValue)?我评论的代码中显示了一个可怜的尝试。

谢谢!

1 个答案:

答案 0 :(得分:0)

首先,正如其他人所指出的那样,您需要vector<unique_ptr<MyObject>>而不是vector<unique_ptr<MyObject*>>。有一个unique_ptr包含一个抽象类(确保基类有一个虚拟析构函数)是很好的。您可以隐式地从包含派生类的unique_ptr转换。

理想情况下,我认为MyCollection::insert应该使用unique_ptr而不是原始指针,以便调用代码首先使用make_unique创建对象,但让我们暂时保留它。

我认为你对make_unique有点困惑。 make_unique旨在创建一个对象并安全地将其包装在unique_ptr中。您的MyCollection::insert实际上并不需要使用make_unique,因为该对象已经创建。 unique_ptr有一个构造函数,它接受一个原始指针,因此你可以直接从原始指针创建一个。

然后,您可以将unique_ptr推送到集合上,或者使用新的unique_ptr罚款替换集合中的unique_ptr

class MyObject {
  public:
    virtual ~MyObject() = 0
};
MyObject::~MyObject() {}

class SimSolverObject : public MyObject {
};

class MyCollection {
  private:
    std::vector<std::unique_ptr<MyObject>> collection;
  public:
    void insert(MyObject* newValue);
};

void MyCollection::insert(MyObject* newValue) {
  //...

  // if we want to add to the collection
    collection.push_back(std::unique_ptr<MyObject>(newValue));

  // if we want to replace at iterator pos in collection
    *pos = std::unique_ptr<MyObject>(newValue);
}

// calling code
MyCollection mc;
MyObject* newValue = new SimSolverObject();
mc.insert(newValue)

如果您决定将MyCollection::insert更改为unique_ptr,则会看起来像这样:

void MyCollection::insert(std::unique_ptr<MyObject> newValue) {
  //... 

  // if we want to add to the collection
  collection.push_back(std::move(newValue));

  // if we want to replace at pos 
  *pos = std::move(newValue);
}

修改:您的for循环看起来有点可疑。我不太确定你要做什么,但你确定要两次增加迭代器吗?一旦进入for的体内,一次进入循环表达式?我怀疑迭代器正在跳过你的状态并超出向量的范围。当它达到索引条件时,可能会留下无效的迭代器。