如何正确使用C++ STL迭代器而不是传统指针?

3

我有一个非常基础的问题。我想在函数中使用STL迭代器来填充数组,而不是传统的C类型指针。我所说的C风格方式如下面的例子:

void f(double* v, size_t n) {
    for (int i = 0; i < n; i++) 
         v[i] = 10;    /* a more reasonable value in practice! */
}

我会使用迭代器将这个转换为C++风格,具体如下:
void f(vector<double>::const_iterator first, vector<double>::const_iterator last) {
    for(vector<double>::iterator it =  first; it != last; it++)
        *it = 10;
}

但我遇到了编译错误。如果我使用iterator而不是const_iterator,问题就会解决。但我在想这是否是正确的做法呢?因为我认为vector.begin()vector.end()迭代器是常数。

提前感谢!


如果您没有修改迭代器指向的内容,应该使用const_iterator,否则,您应该使用iterator - GWW
我想first会被修改,但不会修改last,所以我应该只为last参数使用const_iterator吗?我编写代码的方式通常正确吗? - MikeL
不,我会保持起始和结束迭代器为相同的类型。 - GWW
@ManiBastaniParizi 这不是关于修改 firstlast,而是关于修改它们所指向的内容,当你将值设置为 10 时,显然就会发生这种情况。 - Christian Rau
5个回答

5

The difference between

const vector<double>::iterator

并且

vector<double>::const_iterator

这大致相当于 double * const vconst double *v 之间的区别:

  • 第一个表示迭代器必须保持不变,但它所指向的位置可以被更改。
  • 第二个表示迭代器本身是可变的,但它所指向的位置是 const 的。

如果你将函数改写为:

void f(const vector<double>::iterator first, const vector<double>::iterator last) {
    for(vector<double>::iterator it =  first; it != last; it++)
        *it = 10;
}

它将会编译并正确运行。


如果你写了 vector<double>::iterator const,那么它与 ddouble *const 的相似之处会更清晰明了。 - James Kanze

4
你看到的是由于 const_iterator 大致对应于指向常量的指针。因此,你可以更改迭代器的值,即使它指向其他地方,但不能修改其所指向的内容。
这与 const 迭代器不同,后者不允许增加或减少迭代器。下面是一个例子:
#include <vector>

int main() {
  std::vector<int> v{ 1, 2, 3 };

  std::vector<int>::const_iterator i = v.begin();
  *i = 10;                                         // ERROR!
  ++i;                                             // OK

  std::vector<int>::iterator const ci = v.begin();
  *ci = 10;                                        // OK
  ++ci;                                            // ERROR!
}

1
std::fill(my_vector.begin(), my_vector.end(), 10);

0

由于您正在使用const_iterator,因此无法修改向量。使用非const_iterator是正确的做法。

回答您的最后一个问题,vector.begin()vector.end()都有const_和非const_实现。如果您的向量是非常数,则会获得非const_迭代器。请参阅std::vector::begin的文档。


0
问题在于你的函数使用了 const_iterator,但是你的循环需要一个 iterator,因为你想要修改数据。解决方案当然是让你的函数直接使用 iterator,因为它显然是用来修改范围的。
这与 vector.begin() 返回什么没有任何关系。对于一个 const 对象或引用,它们将返回 const_iterator,否则它们将返回 iterator。但是你的函数明确需要 iterator,因为它修改了传递给它的范围中的值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接