【问题标题】:Why compiler allows send a reference to iterator in function which takes a reference to const iterator?为什么编译器允许在引用 const 迭代器的函数中发送对迭代器的引用?
【发布时间】:2016-11-26 06:29:35
【问题描述】:

我对 const_iterators 有点搞砸了。例如,让我们考虑一下函数:

void functionForConstIterator(std::list<int> const& list, std::list<int>::const_iterator& const_iter)
{
    const_iter = list.begin();
}

现在我可以写了:

void main()
{
    std::list<int> myList = {1, 2, 3, 4, 5};
    std::list<int> const& listRef = myList;
    std::list<int>::iterator iter;

    functionForConstIterator(listRef, iter);
    *iter = 7;

    for (auto it = myList.begin(); it != myList.end(); ++it)
        std::cout << *it << " ";
}

输出为 {7, 2, 3, 4, 5}。为什么?如果我在容器上获得 const 引用,我不必更改它。这是 Visual Studio 2015 编译器。

【问题讨论】:

  • 如果一个函数参数是一个常量引用,那只是意味着函数不能改变它。它不会使它在函数之外开始成为 const。
  • 但这意味着如果我只有 const 引用,而不是容器本身,我总是可以改变它。
  • @πάνταῥεῖ 他指出他正在使用 VS2015 编译器,这意味着您的链接无效,因为它表明 GCC 正确地将其检测为有问题。我怀疑这个问题需要一个 VS2015 标签。

标签: c++ visual-studio-2015 const-iterator


【解决方案1】:

如果我在容器上获得 const 引用,我应该无法更改它。

没错。但是,您没有在容器上获得 const 引用。尽管有它的名字,从语言的角度来看,const_iterator不是const。名称const 是为了向程序员表明您将无法通过此迭代器更改容器。迭代器本身仍然是需要更改的公平目标。

此外,迭代器只是函数内部的const_iterator。在函数之外,即在main 中,它是一个常规的std::list&lt;int&gt;::iterator,在调用函数之前和之后保持完全可变。

【讨论】:

  • 但是如果我只有 const 引用,而不是容器本身,我总是可以更改容器。在这种情况下 const 引用是什么意思?
  • 真正的问题是:是否允许您直接或间接地将 const 迭代器分配给非 const 迭代器并以这种方式修改底层容器。 IMO 的答案应该是
  • 为了进一步澄清我的声明,不应允许隐式或间接地将const_iterator 更改为直iterator
  • @AnyaMitrushchienkova const-ness 与您声明的更大灵活性相关联。您可以通过多种组合选择您想要保持不变的内容。您可以制作一个 const 容器,在这种情况下,编译器不会让您从中制作非常量迭代器。你也可以创建一个const regular 迭代器,在这种情况下编译器不会让你修改迭代器本身,但它会让你修改容器。您可以创建一个非const constant 迭代器,在这种情况下,您可以修改迭代器,但不能修改容器。
【解决方案2】:

Microsoft STL 的 list::iterator 派生自 list::const_iterator。这就是为什么您可以将 iterator 的引用传递给期望 const_iterator 的函数而不会出现问题。

因此,函数内部的赋值是一个切片赋值,但这在这种情况下没有特别的效果,因为iterator 没有虚函数,也没有引入新成员。

因此,由于分配,您已经悄悄地将 const_iterator 转换为 iterator

编辑:我为此创建了一个 Connect 问题:

https://connect.microsoft.com/VisualStudio/feedback/details/2962643

【讨论】:

  • 标准是否禁止这样的实现?
  • 我不认为它在技术上是,因为标准仅在库的极少数地方指定“这可能无法编译”,但它的实施质量肯定很差。
猜你喜欢
  • 1970-01-01
  • 2021-03-30
  • 2016-06-25
  • 2016-04-15
  • 1970-01-01
  • 1970-01-01
  • 2019-10-17
  • 2015-10-24
  • 1970-01-01
相关资源
最近更新 更多