【问题标题】:Does const containers have only const iterator?const 容器是否只有 const 迭代器?
【发布时间】:2015-09-04 14:54:41
【问题描述】:

为什么const STL 容器只返回const_iterators?

例如 std::vectorstd::list 都具有方法 begin 重载 如:

iterator begin();
const_iterator begin() const;
const_iterator cbegin() const;

我认为我仍然可以修改 const 向量的值,但不能修改向量本身。根据标准库没有区别:

const std::vector<int>

const std::vector<const int>

【问题讨论】:

标签: c++ stl iterator standard-library


【解决方案1】:

假设你有

iterator begin() const;

而不是

const_iterator begin() const;

现在,想想当你拥有时会发生什么

const vector<Foo> v;

你将能够做类似的事情

*v.begin() = other_foo;

如果您想保留逻辑常量,这当然不合法。因此,解决方案是在 const 实例上调用迭代器时将返回类型设为 const_iterator

这种情况类似于具有指针成员的const 类。在这些情况下,您可以修改指针指向的数据(但不能修改指针本身),因此不会保留逻辑常量。标准库向前迈进了一步,不允许通过返回 const_iterators 的 const 重载对标准容器进行此类修改。

【讨论】:

  • 但在列表或更复杂的容器中(如树,不存在),容器本身保持不变,因为只有它的节点会被*v.begin() = other_foo;修改。
  • @biowep 取决于您希望界面的行为方式。如果您希望const Container&lt;Type&gt; 等价于Container&lt;const Type&gt;(即保持逻辑常量),那么解决方案是使用const_iterators。如果不是,那么当然取决于您作为迭代器返回的内容。很多时候,尽管保留逻辑常量是一个非常好的主意,否则您最终可能会遇到非常微妙的错误。一般来说,当你写const Container&lt;Type&gt;时,你的意思是一个不能修改元素的容器。
【解决方案2】:

如果您将向量声明为

const std::vector<int> foo;

那么向量本身就是const,这意味着你不能push_backerase等。但是,你可以修改它的元素

for (std::vector<int>::iterator it = foo.begin(); it != foo.end(); ++it)
{
    int& x = *it;
    x++;           // This is fine!
}

当你迭代一个向量时,你强制向量的元素const。所以你可以通过添加和删除东西来修改向量,但你不能修改实际的元素。

std::vector<Foo> values;  // Neither the vector nor its elements are const

for (std::vector<Foo>::const_iterator it = values.cbegin(), it != values.cend(); ++it)
{
    Foo const& foo = *it;         // I may not try to modify foo
    it->CallToNonConstMethod();   // Can't do this either
}

【讨论】:

  • 如果你将 const_iterator 分配给一个迭代器(在 for 循环声明中),那东西将如何编译?这不是合法的转换。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-28
  • 1970-01-01
  • 2018-01-29
  • 1970-01-01
  • 2020-10-02
相关资源
最近更新 更多