1

以下是导致问题的示例:

#include <deque>

int main() {
    std::deque<int> has_data = {1, 2, 3};
    std::deque<int>::iterator iter1 = has_data.begin() + 5; // This works fine
    
    std::deque<int> had_data = {4, 5, 6};
    had_data.clear();
    std::deque<int>::iterator iter2 = had_data.begin() + 5; // This also works fine
    
    std::deque<int> is_empty;
    std::deque<int>::iterator iter3 = is_empty.begin() + 5; // This causes a segfault
}

如果双端队列以前从未包含任何元素,则添加到空双端队列的迭代器似乎是一个问题。

我很好奇这是否是 STL 中的错误,或者我只是以一种导致未定义行为的方式使用它。我只在使用 Xcode(GUI 和命令行)编译时遇到这个问题。我也在 Linux 上使用 GCC 版本 6.2.0 进行了尝试,但问题似乎并不存在。

4

2 回答 2

5

您在这里遇到的问题是,使用操作符将迭代器向前跳转到容器末端之外的位置是未定义的行为。+结果,您正在执行的每个迭代器操作都会导致未定义的行为,而且恰好是前两种情况巧合地不会在最后一种情况下崩溃的情况。

(至于为什么这是未定义的行为:C++17 标准要求(第 27.2.3/2 节),要递增迭代器,迭代器必须是dereferencable,从某种意义上说,取消引用迭代器必须安全且合法在你增加它之前。然后它说(§27.2.7/1)如果你在迭代器上使用+or +=,它应该具有与迭代++执行适当次数相同的效果。因此,如果你跳转迭代器越过容器的末尾一步,在某些时候您将到达容器的末尾,其中迭代器不可取消引用并会触发未定义的行为。)

希望这可以帮助!

于 2020-06-24T00:31:38.650 回答
0

我很好奇这是否是 STL 中的错误,或者我只是以一种导致未定义行为的方式使用它。我只在使用 Xcode(GUI 和命令行)编译时遇到这个问题。

您正在导致未定义的行为。

我也在 Linux 上使用 GCC 版本 6.2.0 进行了尝试,但问题似乎并不存在。

不,未定义的行为在那里以不同的方式表现出来;你尝试它的时候它并没有导致 SEGFAULT。(不过下次你可以试试)

于 2020-06-24T01:13:39.097 回答