如何移植终结迭代器减少? [英] how portable is end iterator decrement?

查看:95
本文介绍了如何移植终结迭代器减少?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的公司源代码刚刚遇到 end()迭代器的减少,对我来说这看起来很奇怪。据我记得,这是在一些平台上工作,但不适用于其他平台。也许我错了,但是在标准方面我找不到任何有用的东西。 Standard仅表示 end()返回一个迭代器,它是过去的结束值,但它是否保证可递减?这样的代码如何匹配标准?

Just encountered decrement of end() iterator in my company source codes and it looks strange for me. As far as I remember this was working on some platforms, but not for the others. Maybe I'm wrong, however I couldn't find anything useful in standard about that. Standard only says that end() returns an iterator which is the past-the-end value, but is it guaranteed to be decrementable? How does code like that match the standard?

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

提前致谢。

推荐答案

我认为这是相关条款:


ISO / IEC 14882:2003 C ++标准23.1 .1 / 12 - 序列

表68列出了为某些类型的
顺序容器而非其他容器提供的序列操作

实施应为容器栏中显示的所有容器类型
提供这些
操作,
应实施它们以便采取
摊销的常数时间。

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 |
    ..............................................................................
    .              .                 .                     .                     .
    .              .                 .                     .                     .

因此对于列出的容器,迭代器不仅应该从 end()返回可递减,递减的迭代器也应该是可解除的。 (当然,除非容器是空的。这会调用未定义的行为。)

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.)

实际上, vector list deque Visual C ++编译器附带的实现与表完全相同。当然,这并不意味着每个编译器都这样做:

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()));
    }






注意代码表:


Note about the code in the table:


ISO / IEC 14882:2003 C ++标准17.3.1.2/6 - 要求

在某些情况下,语义
要求表示为C + +
代码。 此类代码旨在作为
构造与另一个构造
等价的
规范,而不是
必须作为构造
必须实现的方式。

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.end()替换 a.back()的每个实例。 ,反之亦然,并且代码仍然有效。

So while it's true that an implementation may not implement those expressions in terms of begin() and end(), the C++ standard specifies that the two expressions are equivalent. In other words, a.back() and *--a.end() are equivalent constructs according to the above clause. It seems to me that it means that you should be able to replace every instance of a.back() with *--a.end() and vice-versa and have the code still work.

根据Bo Persson的说法,我手头的C ++标准的修订关于表68的缺陷

According to Bo Persson, the revision of the C++ standard that I have on hand has a defect with respect to Table 68.


建议的决议:

更改表68中的规格
可选序列操作在
23.1.1 / 12中a.back()来自

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; }


的规格a.pop_back()来自

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

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

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


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

It appears that you can still decrement the iterator returned from end() and dereference the decremented iterator, as long as it's not a temporary.

这篇关于如何移植终结迭代器减少?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆