使用vector<> :: push_back()时如何使用向量迭代器 [英] How to use vector iterators when using vector<>::push_back()

查看:350
本文介绍了使用vector<> :: push_back()时如何使用向量迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为简单起见,我会坚持 vector< int> 但我认为这适用于任何向量< T> 对象。

For simplicity, I'll stick to vector<int> but I think this applies to any vector<T> object.

如果我使用向量< int> :: iterator 来跟踪某个位置在int的向量中然后我使用 vector< int> :: push_back(),迭代器变得毫无价值。意思是,我不能用& 取消它的地址或取消引用它。一旦我打印出以下意义上的某些对象的地址,直接原因就有了意义:

If I am using a vector<int>::iterator to keep track of some position in a vector of int's and then I use vector<int>::push_back(), the iterator becomes worthless. Meaning, I can't take its address with & or dereference it. The direct reason made sense once I printed the address of some of the objects in the following sense:

vector<int> my_vec(1); //my_vec[0] = 0

vector<int>::iterator it = my_vec.begin(); //it -> my_vec[0], *it = my_vec[0] = 0

cout << "&my_vec = " << &my_vec << "\n";
cout << "&my_vec[0] = " << &my_vec[0] << "\n";
cout << "&it = " << &it << "\n"; //prints address, all good
cout << "*it = " << *it << "\n"; //prints 0, all good

cout << "\n\n" << pushing back..." << "\n\n";
my_vec.push_back(1);

cout << "&my_vec = " << &my_vec << "\n"; //same as before push_back()!
cout << "&my_vec[0] = " << &my_vec[0] << "\n"; //different from before push_back()!!
cout << "&it = " << &it << "\n"; //same as before push_back()
//cannot do &it or *it

显然的地址不会改变,但是 push_back()已经移动了一些东西在内存中,现在 my_vec 的不同元素的地址发生了变化.my_vec [i]有一个新地址的事实对我有意义,但后来我有了以下问题:

So obviously the address of it doesn't change but push_back() has moved things around in memory and now the address of the different "elements" of my_vec are changed. The fact that my_vec[i] has a new address made sense to me but then I have the following questions:

1)为什么 my_vec 的地址不会改变?似乎如果 push_back()导致 my_vec [i] 的地址发生变化,它还应该更改w的地址对象。对于一个数组, my_array 是指向 my_array [0] 的指针,所以我可以想象一个操作改变了每个 my_array [i] 的地址,并更新指针以指向 my_array [0] 的新地址,但是指针的地址 my_array 作为一个对象本身不会改变。但 my_vec 在任何意义上都不是 my_vec [0] 的指针,所以我很困惑为什么<的地址code> my_vec [i] 会改变但不会改变对象 my_vec

1) Why doesn't the address of my_vec change? It seems that if push_back() causes the addresses of the my_vec[i] to change, it should also change the address of the whole object. For an array, my_array is a pointer to my_array[0] so I can imagine an operation changing the addresses of each my_array[i] and updating the pointer to point to the new address of my_array[0] but the address of the pointer my_array as an object in and of itself wouldn't change. But my_vec is not a pointer in any sense to my_vec[0] so I am confused why the addresses of the my_vec[i] would change but not the object my_vec.

2)为什么 vector< int> 内部的任何操作都会改变 my_vec [i] 的地址(例如 push_back())还没有正确更新任何迭代器?这似乎是一个好主意?不是吗?

2) Why would any operation internal to vector<int> that changes the address of the my_vec[i] (such as push_back()) not also properly "update" any iterators? This seems like a good idea? No?

3)鉴于#2就是这样,当我调用 push_back(),处理这个问题的正确方法是什么?如果我需要使用 push_back(),我是否应该使用迭代器?如果有人要抱怨我的用例是使用迭代器和 push_back(),我为了简洁而排除它,但它基本上是使用<$ c实现堆栈$ c> vector< int> 我正在使用迭代器来跟踪堆栈的顶部。由于我不希望启动固定大小,我尝试使用 push_back()在我的迭代器点击 my_vec.end时放大堆栈( )。但我认为这是一个有效的问题。

3) Given that #2 is what it is and my iterators become worthless when I call push_back(), what is the correct way to deal with this? Should I not use iterators if I need to use push_back()? If someone is going to complain about what my use-case is for using iterators and push_back(), I excluded it for brevity but it was basically implementing a stack using vector<int> and I was using an iterator to keep track of the top of the stack. Since I didn't want a fixed size to start, I tried to use push_back() to enlarge the stack when my iterator hit my_vec.end(). But I think this is a valid question in general.

非常感谢你的帮助!

推荐答案


为什么 my_vec 的地址不变?

因为矢量对象本身仍然是同一地址的同一个对象。重新分配会更改它管理的动态数组的地址,而不是管理数组的矢量对象。

Because the vector object itself is still the same object at the same address. Reallocation changes the address of the dynamic array that it manages, not the vector object that manages the array.


为什么任何操作都在 vector< int> 更改 my_vec [i] 的地址(例如 push_back( ))还没有正确更新任何迭代器?这似乎是一个好主意?不是吗?

Why would any operation internal to vector<int> that changes the address of the my_vec[i] (such as push_back()) not also properly "update" any iterators? This seems like a good idea? No?

这会产生(可能很大)运行时成本。向量必须跟踪所有迭代器(需要动态存储,每次创建迭代器时都要分配内存,并在向量更改时更新所有向量)或每个迭代器需要对容器的引用,在每次访问时检查,并且无法实现为简单的指针。 C ++通常会在可能的情况下避免运行时成本 - 特别是在这种情况下,它们几乎总是不必要的。

That would have a (perhaps large) runtime cost. Either the vector would have to track all the iterators (requiring dynamic storage, memory allocation each time an iterator is created, and updating of all vectors when the vector changes) or each iterator would need a reference to the container, checked on every access, and could not be implemented as a simple pointer. C++ generally avoids runtime costs where possible - especially in cases like this, where they are nearly always unnecessary.


什么是正确的交易方式这个?

what is the correct way to deal with this?

有各种选择。您可以存储索引而不是迭代器。你可以使用一个容器,如 std :: list 和稳定的迭代器(尽管效率可能相当低)。如果可以在数组大小上放置上限,则可以保留该数量,以便不需要重新分配。您可以编写自己的容器(或适配器)来自动更新迭代器。对于你的堆栈,如果它确实是一个堆栈,你不需要跟踪除向量末尾之外的任何东西,所以根本不需要存储迭代器。或者你可以使用 std :: stack 而不是重新发明它。

There are various options. You could store an index rather than an iterator. You could use a container such as std::list with stable iterators (although that might be rather less efficient). If you can place an upper bound on the size of the array, you could reserve that amount so that reallocation won't be necessary. You could write your own container (or adapter) that automatically updates iterators. For your stack, if it is indeed a stack, you shouldn't need to track anything other than the end of the vector, so there's no need to store an iterator at all. Or you could use std::stack rather than reinventing it.


是否有任何其他向量< T> 成员函数(除了明显的那些)对迭代器有这种影响吗?

Are there any other vector<T> member functions (besides the obvious ones) that have this effect on iterators?

当任何操作导致向量增长超过其当前容量时,迭代器将被重新分配无效。您可以使用 reserve 函数控制容量。

Iterators are invalidated by reallocation, when any operation causes the vector to grow beyond its current capacity. You can control the capacity with the reserve function.

此外,擦除元素将使任何指向已擦除的迭代器无效元素或序列中的元素。

Also, erasing elements will invalidate any iterator referring to the erased elements, or elements later in the sequence.

这篇关于使用vector&lt;&gt; :: push_back()时如何使用向量迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆