C ++预先分配的包含指针的对象向量

时间:2013-03-23 01:50:13

标签: c++ vector

我有以下结构:

struct CacheNode {
  set<int> *value;
  int timestamp;
  CacheNode() : value(new set<int>()), timestamp(0) {}
};

我预先分配了一个矢量,如下所示:

vector<CacheNode> V(10);

执行此操作时,向量中的每个CacheNode元素都指向其set<int>字段中的相同value。特别是,

  V[0].value->insert(0);
  cout << V[1].value->size() << endl;

打印出1而不是我想要的0

预先分配向量(或声明结构)的正确方法是什么,以便每个CacheNode都有自己的set<int>实例?

(注意:我确实需要value作为指向集合的指针,因为在我的应用程序中可以让一些CacheNodes共享集合。)

3 个答案:

答案 0 :(得分:5)

vector<CacheNode> V(10);创建一个初始CacheNode对象,然后将其复制10次。所以你有10个相同的对象。

您可以使用generate_n

std::vector<CacheNode> v;
std::generate_n(std::back_inserter(v), 10u, [](){ return CacheNode{}; });

这是一个example program

答案 1 :(得分:5)

您违反了3的规则。您创建了一个具有非平凡构造函数的对象,但无法创建析构函数或复制构造函数或operator=

std::vector<blah> foo(10)创建一个默认构造的blah,并在foo中制作10个副本。因为你违反了3规则,所以这10份副本都是相同的。

最简单的方法是取消new

struct CacheNode {
  std::set<int> value;
  int timestamp;
  CacheNode() : value(), timestamp(0) {}
};

另一种方法是使用unique_ptr进行生命周期管理,并明确复制:

struct CacheNode {
  std::unique_ptr<std::set<int>> value;
  int timestamp;
  CacheNode() : value(new std::set<int>()), timestamp(0) {}
  CacheNode(CacheNode&&) = default; // C++11 feature
  CacheNode(CacheNode const& other):value(new std::set<int>( *other.value ) ), timestampe(other.timestamp) {}

  CacheNode& operator=(CacheNode const& other) {
    value.reset(new std::set<int>(*other.value));
    timestampe = other.timestamp;
    return *this;
  }
  CacheNode& operator=(CacheNode&& other) = default;
  // no need for ~CacheNode, unique_ptr handles it
};

如果您想从std::set<int>中取出CacheNode,请致电CacheNode().value.release()并存储生成的std::set<int>*

std::shared_ptr<std::set<int>>将允许std::set的共享所有权。

还有其他方法,包括使vector存储指针指向CacheNode,创建具有重要语义的value_ptr<T>模板等。

在C ++ 11中,这些相对容易且安全,因为std::vector会移动事物,并且在value_ptr<T>上移动语义不会创建新的T。< / p>

我对你在不同std::set<int>之间共享CacheNode的计划有点怀疑,因为一般来说这是难闻的气味 - 事情的所有权/生命周期应该是明确的,在这种情况下你有一些CacheNode拥有std::set<int>而另一些拥有shared_ptr(因为他们共享所有权)。 {{1}}可以解决这个问题,但通常会有更好的解决方案。

答案 2 :(得分:-1)

你会想要使用vector.assign(10, CacheNode()),因为你所做的事情主要是保留空间。

另外你应该做其他人说的,提供虚拟析构函数等。