2
#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>
using namespace std;

class Derived
{
public:
        int i;
        Derived() {cout<<"Constructed Derived"<<endl;}
        Derived(int ii):i(ii) {cout<<"Constructed Derived"<<i<<endl;}
        ~Derived() {cout<<"* Destructed Derived"<<i<<endl;}
};

int main()
{
   boost::ptr_vector<Derived> pv;
   for(int i=0;i<10;++i) pv.push_back(new Derived(i));

   boost::ptr_vector<Derived>::iterator it;
   for (it=pv.begin(); it<pv.end();/*no iterator increment*/ )
        pv.erase(it);
   cout<<"Done erasing..."<<endl;
}

请注意,第二个 for 循环不会增加迭代器,但它会迭代并擦除所有元素。我的问题是:

  1. 我的迭代技术和使用迭代器是否正确?
  2. 如果 for 循环中不需要迭代器增量,那么增量发生在哪里?
  3. 使用迭代器更好还是普通整数就足够了(即:使用迭代器是否有任何增值)?(因为我也可以像 pv.erase(pv.begin()+5); 一样擦除第 5 个元素;)
  4. 有没有办法直接将新对象分配给 ptr_vector 的特定位置(比如说第 5 个位置)?我正在寻找类似 pv[5]=new Derived(5); 的东西。有什么办法吗?
4

2 回答 2

3

Aptr_vector::iterator就像普通的随机访问迭代器一样递增。在您的示例中,您可以在不实际增加的情况下擦除每个元素,因为在擦除一个元素之后,它之后的每个元素都会在数组中移动。因此,当您删除第 0 个元素时,您的迭代器现在指向曾经是第 1 个元素但现在是第 0 个元素的元素,依此类推。换句话说,当整个向量向左移动时,迭代器保持原位。

这与 ptr_vector 无关。请注意,普通的std::vector.

另请注意,在擦除它指向的元素后使用迭代器是危险的。在您的情况下,它可以工作,但最好采用返回值,ptr_vector::erase这样您就可以得到一个保证有效的新迭代器。

 for (it = pv.begin(); it != pv.end(); )
        it = pv.erase(it);

至于你的其他问题:

如果您只想擦除特定元素,那么您当然应该直接使用pv.erase(pv.begin() + N). 要将新值分配给指针向量中的特定元素,只需说pv[N] = Derived(whatever). new重新分配值时不需要使用。指针向量将在您分配新值的索引处调用对象的赋值运算符。

于 2010-10-23T09:44:42.017 回答
1

我的迭代技术和使用迭代器是否正确?

不,从容器中擦除通常会使被擦除项目的迭代器无效。如果它有效,这只是实现细节的副作用。

正确的方法是使用擦除方法的返回值:

 it = pv.erase(it);

但是,为了清空容器,您可以使用 clear 成员函数。

如果 for 循环中不需要迭代器增量,那么增量发生在哪里?

它不会发生,因为您将始终擦除容器中的第一个项目(碰巧,可能不适用于其他容器)。

使用迭代器更好还是普通整数就足够了(即:使用迭代器是否有任何增值)?(因为我也可以像这样擦除第五个元素 pv.erase(pv.begin()+5);

在随机访问容器中,您可以这样做,否则不能(例如列表)。

有没有办法直接将新对象分配给 ptr_vector 的特定位置(比如说第 5 个位置)?我正在寻找类似的东西pv[5]=new Derived(5);。有什么办法吗?

根据升压参考:

pv.replace(5, new Derived(5));

这将返回智能指针中的现有指针,因此它将被自动释放。(奇怪的是这需要一个索引,而不是一个迭代器......)。

或者:

pv[5] = Derived(5);

但这只会修改存储的对象,而不是更改指针。

于 2010-10-23T10:13:16.927 回答