c++ - 结束迭代器递减的可移植性如何?

标签 c++ stl iterator portability

刚刚在我的公司源代码中遇到了 end() 迭代器的减量,这对我来说看起来很奇怪。据我记得,这适用于某些平台,但不适用于其他平台。也许我错了,但是我在标准中找不到任何有用的东西。标准只说 end() 返回一个迭代器,它是过去的值,但它保证是可递减的吗?这样的代码如何符合标准?

std::list<int>::iterator it = --l.end();

提前致谢。

最佳答案

我认为这是相关条款:

ISO/IEC 14882:2003 C++ Standard 23.1.1/12 – Sequences

Table 68 lists sequence operations that are provided for some types of sequential containers but not others. An implementation shall provide these operations for all container types shown in the "container" column, and shall implement them so as to take amortized constant time.

    +----------------------------------------------------------------------------+
    |                                  Table 68                                  |
    +--------------+-----------------+---------------------+---------------------+
    |  expression  |   return type   |     operational     |      container      |
    |              |                 |      semantics      |                     |
    +--------------+-----------------+---------------------+---------------------+
    | a.front()    | reference;      | *a.begin()          | vector, list, deque |
    |              | const_reference |                     |                     |
    |              | for constant a  |                     |                     |
    +--------------+-----------------+---------------------+---------------------+
    | a.back()     | reference;      | *--a.end()          | vector, list, deque |
    |              | const_reference |                     |                     |
    |              | for constant a  |                     |                     |
    ..............................................................................
    .              .                 .                     .                     .
    .              .                 .                     .                     .
    ..............................................................................
    | a.pop_back() | void            | a.erase(--a.end())  | vector, list, deque |
    ..............................................................................
    .              .                 .                     .                     .
    .              .                 .                     .                     .

So for the containers listed, not only should the iterator returned from end() be decrementable, the decremented iterator should also be dereferencable. (Unless the container is empty, of course. That invokes undefined behavior.)

In fact, vector, list and deque implementations that came with the Visual C++ compiler does it exactly like the table. Of course, that's not to imply that every compiler does it like this:

// From VC++'s <list> implementation

reference back()
    {    // return last element of mutable sequence
    return (*(--end()));
    }

const_reference back() const
    {    // return last element of nonmutable sequence
    return (*(--end()));
    }

注意表中的代码:

ISO/IEC 14882:2003 C++ Standard 17.3.1.2/6 – Requirements

In some cases the semantic requirements are presented as C + + code. Such code is intended as a specification of equivalence of a construct to another construct, not necessarily as the way the construct must be implemented.

因此,虽然实现可能不会根据 begin()end() 实现这些表达式,但 C++ 标准规定这两个表达式是等价的.换句话说,a.back()*--a.end() 是根据上述条款的等效结构。在我看来,这意味着您应该能够将 a.back() 的每个实例替换为 *--a.end() ,反之亦然,让代码仍然有效。


根据 Bo Persson,我手头上的 C++ 标准修订版 has a defect关于表 68。

Proposed resolution:

Change the specification in table 68 "Optional Sequence Operations" in 23.1.1/12 for "a.back()" from

*--a.end()

to

{ iterator tmp = a.end(); --tmp; return *tmp; }

and the specification for "a.pop_back()" from

a.erase(--a.end())

to

{ iterator tmp = a.end(); --tmp; a.erase(tmp); }

看来您仍然可以递减从 end() 返回的迭代器并取消引用已递减的迭代器,只要它不是临时的。

关于c++ - 结束迭代器递减的可移植性如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5322104/

相关文章:

c++ - 我们可以安全地依赖迭代器 v.end() 的位置吗?

c++ - DirectX 11 - 使用 AVX 的 AoS 到 SoA 转换导致重新映射时顶点缓冲区损坏

c++ - 链接器错误 - 带有 libboost_thread 的 macOS 上 undefined symbol std::string::c_str() const?

c++ - 使用现有的 cpp 核心代码构建 Web 应用程序

c++ - 如何使用区分大小写的元素对 std::list 进行排序?

c++ - 迭代器如何映射/知道它们的当前位置或元素

python - 单线检查迭代器是否产生至少一个元素?

c++ - 避免在多线程套接字应用程序中重复使用相同的 fd 号

c++ - 什么是auto_ptr_ref,它实现了什么以及如何实现的

C++ vector::clear() - 破坏顺序?