#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循环不会递增迭代器,但它会迭代并擦除所有元素。我的问题是:
- 我的迭代技术和使用迭代器是否正确?
- 如果for循环中不需要迭代器增量,那么增量发生在哪里?
- 使用迭代器或者普通的整数是否更好(即:使用迭代器是否有任何增值)? (因为我也可以删除第5个元素,如pv.erase(pv.begin()+ 5);)
- 有没有办法直接将新对象分配到ptr_vector的特定位置(比如第5位)?我正在寻找类似pv [5] = new Derived(5);的东西。这样做的任何方式?
醇>
答案 0 :(得分:3)
ptr_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
。指针向量将在您为其赋值的索引处调用对象的赋值运算符。
答案 1 :(得分:1)
我的迭代技术和使用迭代器是否正确?
不,从容器中删除通常会使删除项的迭代器无效。如果它有效,这只是实现细节的副作用。
正确的方法是使用erase方法的返回值:
it = pv.erase(it);
但是,要清空容器,可以使用clear member函数。
如果for循环中不需要迭代器增量,那么在哪里 增量是否会发生?
它不会发生,因为你总是会删除容器中的第一个项目(偶然,可能无法与其他容器一起使用)。
使用迭代器或普通整数是否更好(即: 使用时是否有任何增值功能 迭代器)? (因为我也可以删除 第5个元素
pv.erase(pv.begin()+5);
)
在随机访问容器中,您可以这样做,否则不能(例如列表)。
有没有办法将新对象分配到特定位置(让我们 说ptr_vector的第5个位置, 直?我正在寻找一些东西 比如
pv[5]=new Derived(5);
。无论如何 这样做?
根据提升参考:
pv.replace(5, new Derived(5));
这将返回智能指针中的现有指针,因此它将自动释放。 (很奇怪这需要一个索引,而不是一个迭代器......)。
或者:
pv[5] = Derived(5);
但这只会修改存储的对象,而不是更改指针。