指针向量的迭代器

iterators for vector of pointers

本文关键字:迭代器 向量 指针      更新时间:2023-10-16

我读了另一篇文章,回答了一个关于指针向量迭代器的问题。我试图在我的代码中使用相同的概念,但我收到一些编译错误。我基于的代码示例是:

vector<c*> cvect;
cvect.push_back(new sc);
vector<c*>::iterator citer;
for(citer=cvect.begin(); citer != cvect.end(); citer++) {
    (*citer)->func();
}

我想使用类似的概念为一个类创建一个深度复制构造函数,该类有两个数据成员,它们是指向对象的指针的向量。我的代码类似于这样:

class MyContainer {
    vector<MyStuff*> vecOne;
    vector<MyStuff*> vecTwo;
 public:
    MyContainer(const MyContainer& other);
};
MyContainer::MyContainer(const MyContainer& other) {
    // copy vector one
    vector<MyStuff*>::iterator vec1_itr;
    for (vec1_itr = other.vecOne.begin(); vec1_itr != other.vecOne.end(); vec1_itr++) {
        vecOne.push_back(new MyStuff(vec1_itr));
    }
    // copy vector two
    vector<MyStuff*>::iterator vec2_itr;
    for (vec2_itr = other.vecTwo.begin(); vec2_itr != other.vecTwo.end(); vec2_itr++) {
        vecTwo.push_back(new MyStuff(vec2_itr));
    }
}
我得到一些编译错误,如:

/path/MyContainer.cpp:38: error: ' operator= ' in ' vec1_Itr = other->MyContainer::vecOne. std::vector<_Tp, _Alloc>::begin [with _Tp = MyStuff*, _Alloc = std::allocator<MyStuff*>]() ' no match

候选者为:__gnu_cxx::__normal_iterator<MyStuff*, std::vector<MyStuff, std::allocator<MyStuff> > >& __gnu_cxx::__normal_iterator<MyStuff*, std::vector<MyStuff, std::allocator<MyStuff> > >::operator=(const __gnu_cxx::__normal_iterator<MyStuff*, std::vector<MyStuff, std::allocator<MyStuff> > >&)

我也得到一个错误的operator!=…另一个向量的另一组相同的错误

您忘记对迭代器解引用了。试试这个:

vecOne.push_back(new MyStuff( **vec1_itr ));

编辑0:

是的,应该是双解引用(如上所述)。它应该是const_terator,因为你正在处理const包含对象:

vector<MyStuff*>::const_iterator vec1_itr;

要么不将参数作为const,要么将vec1_itr声明为const_iterator。这里的问题是vecOne.begin()返回const_iterator,因为容器是const。如果你想改变容器,你必须删除const限定符。

另外,如果持有一个指针容器意味着你需要管理容器中的指针,并且你有两个这样的容器,那么你应该将容器移动到它自己的类中。尽量避免管理一个类中的多个资源。

!!内存泄漏警报!!

你的代码是有漏洞的。

从复制构造函数(std::bad_alloc ?)中抛出的任何异常都会导致内存泄漏,因为传递到vector的内存永远不会被清理(析构函数不会被调用,因为对象从一开始就没有被构造)。

当然,您可以添加所需的try/catch,但我警告您,代码很快就会变得笨拙(您需要几个)。 这是违反资源管理规则1的直接结果:

一个对象应该最多管理一个资源,在这种情况下,它不应该做任何其他事情。

这意味着如果你的对象是一个业务对象(里面有应用程序逻辑),那么它不应该直接处理资源管理,而是使用已经存在的管理器。

在您的情况下,您有两个解决方案:

  1. 推荐:因为这里不使用多态性,所以不要使用指针。std::vector<MyStuff>非常好
  2. 如果您需要多态性,但没有在这个玩具示例中包含它,那么使用boost::ptr_vector<MyStuff>

附加说明:它们定义了合理的复制构造函数、赋值操作符和析构函数,因此您不必自己重写它们。

编辑:

正如@David所指出的,如果需要多态性,就不能使用复制构造,因此需要:

  • clone方法,或等效的
  • 指针和动态内存分配

boost::ptr_vector提供了您所需要的一切(在复制时自动使用clone方法)。