为什么调用std::vector::back()会导致我的程序崩溃?

7

我不确定这段代码有什么问题:

std::vector<int> myVector(0);

if (myVector.back() == 12)
    myVector.push_back(12);

看起来在空向量上调用back()会导致程序崩溃。

我不明白为什么会崩溃?我们需要在调用back()之前检查向量的长度吗?或者可能是一个错误吗?

文档说,如果向量为空,则返回一个未定义的值。


1
我怀疑这是因为有人认为你使用 MSDN 作为参考而不是 C++ 标准,所以给了你 -1 分。实现者可以进一步定义在标准规定为未定义行为的情况下他们的实现会做什么,因此如果 MS 想要保证在使用空向量时 back() 函数会返回,他们是有权这样做的。如果你正在使用 MSVC++,那么你有权阅读他们的文档。但是,如果没有意识到任何方式中使用“未定义值”可能会导致崩溃,则可能会得到 -1 分。 - Steve Jessop
@SteveJessop 我认为MSDN是C++标准的实现。但是,调用一个有效元素上的方法(据我所知,空向量是一个有效元素)导致我的程序崩溃,这感觉很奇怪。如果标准这样规定,那就这样吧 :) - MBen
1
MSVC++是(大约)C++标准的一种实现。如果标准没有规定行为,其他实现会有不同的行为。标准没有定义在空向量上调用back()的原因是为了让实现不需要特殊情况下的代码。它们可以选择比它们检查向量是否为空时更快,并在不同情况下执行不同的操作。当您做错事情时,它们容易崩溃(或更糟)。这可能感觉很奇怪,但这是语言设计的一部分所做出的权衡。 - Steve Jessop
2个回答

15

在调用back()之前,我们需要检查向量的长度吗?

简单来说:是的。这是你的错误,你的向量是空的,所以没有“back”元素。

文档应该说明(如果它有任何说明),在空向量上调用back()会导致未定义的行为,而不是返回未定义的值。


由于某种原因,MSDN确实说“返回值未定义”(http://msdn.microsoft.com/en-us/library/0532x4xk%28v=vs.80%29.aspx)。但它也说:“当使用_SECURE_SCL 1编译时,如果尝试访问空向量中的元素,则会发生运行时错误。”我不知道(a)为什么MS将引用称为“值”,或者(b)他们如何将“未定义值”的概念与导致运行时错误的引用概念相一致。但是,该运行时错误可能就是提问者描述的“崩溃”现象。 - Steve Jessop
我仍然觉得奇怪,调用有效元素上的方法会导致我的程序崩溃。 - MBen
@MBen:但是你的向量中没有元素;back() 的前提条件是你的向量至少有一个元素。这就是接口定义的方式。在尝试调用 back() 之前,您需要确保您的输入符合前提条件。 - CB Bailey
@MBen:回顾您的评论,当您说“在有效元素上”时,是指“在有效对象上”吗?我想我可能误解了您所写的内容。 - CB Bailey
@CharlesBailey 是的,抱歉,我的意思是空向量是一个有效的元素,它不是垃圾或空值,这就是我感到惊讶的原因 :-) - MBen

6

c++11标准规定如下:

23.3.2.8 / 3

调用空数组的front()或back()方法是未定义的。

由于行为是未定义的,任何事情都可能发生。你很幸运只是遇到了崩溃。


我不认为自己很幸运,调用一个有效值的方法却导致程序崩溃感觉很奇怪。 - MBen
4
程序在出现未定义行为时崩溃是好事情,因为这样更容易捕捉到错误。如果程序有时能正常运行,有时又不能,那么很难找到错误所在。 - BЈовић
我同意。我只需要确保这个向量有元素 :-) - MBen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接