【问题标题】:How smart is C++ deque iteratorC++双端队列迭代器有多聪明
【发布时间】:2017-05-20 16:16:31
【问题描述】:

假设我有一个包含 100 个值的 std::deque<int> d,从 099。给定the following

与向量不同,双端队列不能保证将所有元素存储在 连续的存储位置:访问双端队列中的元素 将指针偏移到另一个元素会导致未定义的行为。

下面的行似乎无效:

int invalidResult = *(d.begin() + 81); // might give me 81, but NOT GUARANTEED, right?

我的问题是:迭代器会处理这个问题吗?

std::deque<int>::iterator it = d.begin();
int isThisValid = *(it + 81); // 81 every time? or does it result in undefined behavior?

在某一时刻,我曾认为迭代器会处理底层存储中的任何不连续性,但现在我不太确定。显然,如果你使用it++ 81 次,*it 将给你81 结果。

有人可以肯定地说吗?

不管怎样,我没有使用 C++11。

【问题讨论】:

  • “通过偏移一个指针”的哪一部分与d.begin() + 81有关系?
  • 你问的是双端队列迭代器是否是随机访问的?是的。是的。
  • @KerrekSB 所以他们想说“不要取一个元素的地址然后从那里偏移”?
  • @kmort 是的,这正是他们想说的。与向量不同,双端队列的存储不是连续的。
  • @kmort:是的,这就是“指针”通常的意思。

标签: c++ stl deque


【解决方案1】:

下面的行似乎无效:

int invalidResult = *(d.begin() + 81); // might give me 81, but NOT GUARANTEED, right?

相反。该声明完全有效并且行为得到保证(假设d.size() &gt;= 82)。这是因为std::deque::begin 返回的是一个迭代器,而不是一个指针,所以引用的规则不适用。

std::deque<int>::iterator it = d.begin();
int isThisValid = *(it + 81); // 81 every time? or does it result in undefined behavior?

这几乎等同于前面的代码,只是您使用了命名变量,而不是临时迭代器。行为完全相同。


这是一个你不能做的例子:

int* pointer = &d.front();
pointer[offset] = 42; // oops

【讨论】:

  • 好的。我很高兴迭代器透明地处理任何不连续性。这意味着我必须在别处寻找我看到的错误。谢谢!
  • 您可以从迭代器获得更多保证:std::deque::begin() 当前 (C++17) 返回一个 LegacyRandomAccessIterator (en.cppreference.com/w/cpp/named_req/RandomAccessIterator),这意味着 d.begin() + 81O(1) 中(而调用it++ 81 次是在O(n)),这可以显着提升性能。
【解决方案2】:

根据this reference herestd::deque 提供RandomAccessIterator,根据您的示例肯定会起作用。

std::deque<int>::iterator it = d.begin();
int isThisValid = *(it + 81); // will be fine assuming the deque is that large

【讨论】:

    猜你喜欢
    • 2015-06-26
    • 2010-12-12
    • 1970-01-01
    • 2019-10-07
    • 2014-03-14
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 2010-10-29
    相关资源
    最近更新 更多