我有一个类,它产生任意数量的worker对象,将其结果计算为std::vector
。我将在某些点移除一些工作对象,但我想将它们的结果保持为只有spawned
类的类才知道的某个顺序。因此,我在A类中为输出提供了向量。
我有(IMO)三个选项:我可以指向矢量,引用或迭代器作为成员。迭代器选项有一定的缺点(迭代器可以递增。)我不确定指针或引用是否更清晰。 我觉得引用更好,因为它们不能为NULL,并且cruncher需要存在向量。
我最不确定的是参考文献的有效性。它们会因std::list< std::vector<int> >
上的某些操作而失效吗?这些操作是否与使std::list
的迭代器无效相同?还有另一种我现在看不到的方法吗?此外,与容器的耦合感觉不对:我强制将特定容器强制到Cruncher类。
为清晰起见而提供的代码:
#include <list>
#include <vector>
#include <boost/ptr_container/ptr_list.hpp>
class Cruncher {
std::vector<int>* numPointer;
std::vector<int>& numRef;
std::list< std::vector<int> >::iterator numIterator;
public:
Cruncher(std::vector<int>*);
Cruncher(std::vector<int>&);
Cruncher(std::list< std::vector<int> >::iterator);
};
class A {
std::list< std::vector<int> > container;
boost::ptr_list< std::vector<int> > container2;
std::vector<Cruncher> cruncherList;
};
答案 0 :(得分:6)
如果迭代器失效,它也会使迭代器转换为的指针/引用无效。如果你有这个:
std::vector<T>::iterator it = ...;
T *p = &(*it);
T &r = *p;
如果迭代器无效(例如对push_back的调用可能使所有现有的向量迭代器无效),则指针和引用也将失效。
从标准23.2.4.2/5(载体容量):
注意:重新分配使引用序列中元素的所有引用,指针和迭代器无效。
相同的一般主体适用于std :: list。如果迭代器失效,则转换为迭代器的指针和引用也会失效。
std :: list和std :: vector之间的区别是导致迭代器失效的原因。只要您不删除它所引用的元素,std :: list迭代器就是有效的。因此,std::vector<>::push_back
可以使迭代器无效,std::list<>::push_back
不能。
答案 1 :(得分:1)
如果在生成工作线程后重新分配父元素的向量内容,则它们的指针,引用,迭代器或其他任何几乎肯定无效。列表可能不同(给定它们如何分配)但我不知道,甚至可能与平台有关。
基本上,如果你有多个工作线程,那么实际上在父类上有一个方法可以最安全地将结果转储回来,只要副本不那么费力。当然它不如直接分配给父母那么好,但是你需要确保你所倾倒的容器在重新分配时不会“丢失”。
如果您正在使用的列表保证在添加(或删除)成员时不重新分配其“其他”空间,那么这将实现您正在寻找的内容,但该向量肯定是不安全的。但无论哪种方式,只要您的“根容器”不会移动其内容,您访问它的方式(指针,引用或迭代器)可能并不重要
编辑:
正如下面的评论所述,这是一个关于SGI's website(强调我的)列表的块:
列表具有重要的属性 插入和拼接不 使迭代器无效以列出元素, 甚至删除只会失效 指向的迭代器 被删除的元素。 迭代器的排序可能会改变 (也就是说,list :: iterator可能有 不同的前任或继任者 列表操作后比它做的 之前),但迭代器本身 不会失效或作出 指向不同的元素,除非 失效或突变是 明确的。
所以这基本上说“使用列表作为你的主存储”,然后每个工作者都可以转储到自己的工作室,并且知道当另一个工人完全完成并且他们的矢量从列表中删除时它不会失效。 / p>
答案 2 :(得分:0)
在当前版本的C ++中(即没有移动构造函数),嵌入std :: list中的项的指针将与列表迭代器一起失效。
如果你使用了std :: list *&gt;,那么vector *可以移动但是矢量不会,所以你指向vector的指针仍然有效。
通过在C ++ 0x中添加移动构造函数,除非向量本身被调整大小,否则向量内容可能会保持不变,但任何此类假设本质上都是不可移植的。
答案 3 :(得分:0)
我喜欢指针参数。这是一种风格问题。我更喜欢这种参数类型样式:
正如您所说,迭代器会在父容器类型上创建无意义的依赖关系。 (std :: list实现为双链表,因此只删除它的条目会使向量无效。所以它会起作用。)