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

Jac*_*eng 0 c++ vector

我有以下结构:

struct CacheNode {
  set<int> *value;
  int timestamp;
  CacheNode() : value(new set<int>()), timestamp(0) {}
};
Run Code Online (Sandbox Code Playgroud)

我预先分配了它们的向量,如下所示:

vector<CacheNode> V(10);
Run Code Online (Sandbox Code Playgroud)

当我这样做时,CacheNode向量中的每个元素set<int>在其value字段中指向相同的元素.特别是,

  V[0].value->insert(0);
  cout << V[1].value->size() << endl;
Run Code Online (Sandbox Code Playgroud)

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

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

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

Sta*_*ked 5

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

你可以使用generate_n:

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

这是一个示例程序.


Yak*_*ont 5

您违反了3的规则.您已经使用非平凡的构造函数创建了一个对象,并且无法创建析构函数或复制构造函数或operator=.

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

最简单的方法是取消new:

struct CacheNode {
  std::set<int> value;
  int timestamp;
  CacheNode() : value(), timestamp(0) {}
};
Run Code Online (Sandbox Code Playgroud)

另一条路线是使用a 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
};
Run Code Online (Sandbox Code Playgroud)

当你想要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.

我对你std::set<int>在不同之间分享的计划有点怀疑CacheNode,因为一般来说这是难闻的气味 - 事物的所有权/生命周期应该是清楚的,在这种情况下,你有一些CacheNode拥有std::set<int>和其他人没有(因为他们共享所有权).A shared_ptr可以解决这个问题,但通常有更好的解决方案.

  • @Antimony是的,这确实会引起并发症.有些人共享所有权,而其他人没有,并希望复制创建一个新的缓冲区而不移动,这个类的语义的脆弱性正在变得严重问题. (2认同)