【问题标题】:Should conversions from non-const iterator to const iterator be avoided?是否应该避免从非常量迭代器到常量迭代器的转换?
【发布时间】:2019-03-30 00:03:58
【问题描述】:

我试图将const iteratornon-const iterator 进行比较,但不确定是否可以,所以我查了一下。我发现这是可以的,因为隐式转换 non-const iteratorconst iterator。但是,我想知道您是否应该不比较这些迭代器,以避免这种转换。例如,

begin_iterator = buf.begin();  end_iterator = buf.cend();
for (; begin_iterator != end_iterator; ++begin_iterator) { ... }

通常,我认为这没问题,因为 const 表示只读,这很好。但是,我不确定(不必要的)转换。

【问题讨论】:

  • 我怀疑是否有任何转换。可能有一个重载的!=

标签: c++ iterator const-iterator


【解决方案1】:

将非 const 迭代器转换为 const 迭代器总是好的,就像将非 const 指针转换为 const 指针一样。

相反的事情不是你想要做的,它可能会导致崩溃(例如,因为数据存储在 const only 空间中)。所以永远不要这样做。

【讨论】:

  • 如果数据实际上不是 const,则不是未定义的行为。例如int a = 1; const int * b = &a; *const_cast<int*>(b) = 3; 很好
  • 同意,如果您知道数据的来源。但总的来说,你不会,所以它是UB。
  • 嗯,一般来说你不知道它是否是 UB,所以你不要这样做
  • 确实如此。我已经删除了 UB 并保留了“不要这样做”。谢谢。
【解决方案2】:

虽然这可能适用于这种情况,但它不是创建范围的标准模式。特别是,标准算法需要两个相同类型的迭代器,因此,例如,std::fill(whatever.begin(), whatever.cend(), 3) 将无法编译。

因此,问题中的代码会产生维护问题。假设维护者意识到 for 循环正在做一些可以用标准算法完成的事情。显而易见的转变是用算法替换 for 循环。所以

begin_iterator = buf.begin();  end_iterator = buf.cend();
for (; begin_iterator != end_iterator; ++begin_iterator) { ... }

变成

begin_iterator = buf.begin();  end_iterator = buf.cend();
std::whatever(begin_iterator, end_iterator);

但是这样编译不通,所以维护者要四处寻找,发现这两个迭代器不是同一种类型,然后弄清楚是否可以改变结束的类型迭代器以匹配开始迭代器。这意味着检查所有使用 end 迭代器的地方,以确定为什么它是不同的类型以及这是否重要。

所以真正的问题是,这解决了什么问题,成本是否值得?一般来说,第一个答案是“不重要”,第二个答案是“不”。

【讨论】:

    猜你喜欢
    • 2013-09-13
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-20
    • 1970-01-01
    相关资源
    最近更新 更多