我有以下结构:
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共享集合。)
答案 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())
,因为你所做的事情主要是保留空间。
另外你应该做其他人说的,提供虚拟析构函数等。