这里有另一个快速问题,我有这段代码:
string sa[6] = {
"Fort Sumter", "Manassas", "Perryville",
"Vicksburg", "Meridian", "Chancellorsville" };
vector<string> svec(sa, sa+6);
for (vector<string>::iterator iter = svec.begin(); iter != svec.end(); iter++)
{
std::cout << *iter << std::endl;
}
为什么当我执行svec(sa,sa + 7)时,代码可以工作,但是在最后一个单词之后打印出一个空行,当我执行sa + 8而不是崩溃时?因为字符串数组只有6个元素大,所以它不应该在sa + 7处崩溃吗?
感谢。
答案 0 :(得分:11)
访问向量的末尾是未定义的行为。什么事情都可能发生。您可能有nasal demons。
答案 1 :(得分:5)
您的应用程序不会崩溃,因为有一些标准指定它应该崩溃。崩溃只是随机(未定义)行为。当你发现超出数组范围时,你不会总是遇到崩溃。
基本上,任何事情都可能发生,例如打印空行,崩溃甚至刚发布 - 让恶魔飞出你的鼻子。
答案 2 :(得分:5)
你有一个只有六个元素的数组。当您尝试访问所谓的“第七”元素时,您将获得未定义的行为。从技术上讲,这意味着任何事情都可能发生,但在我看来,这似乎不是一个非常有用的解释,所以让我们仔细看看。
该数组占用内存,当您访问元素超出结束时,您正在读取占用该内存的任何值。 可能该地址不属于您的进程,但它可能是,因此读取驻留在该空间中的sizeof(string)
字节通常是安全的。
您的程序从中读取,并且由于它是通过string
数组读取的,因此它将该内存视为真正的string
对象。 (你的程序无法区分它。它不知道更好。它只是试图执行你的指示。)显然,无论发生什么数据都看起来像一个真正的string
对象,你的程序能够像对待它一样,至少足够长,以便在vector
中复制它,然后打印它的(空)值。这次工作有效,但这并不意味着它每次都会起作用。
阵列的“第八”位置的数据没有运气。它看起来不像有效的string
对象。 string
对象通常包含指向字符数据的指针以及长度。也许通常代表该指针的对象区域不包含程序的有效地址。或者,表示长度字段的部分可能包含的值远远大于指针中地址的可用值。
答案 3 :(得分:2)
C ++不对数组进行范围检查。
超出数组末尾的读取是所谓的“未定义”行为:即不能保证抛出异常,不保证不抛出异常,并且不能保证一致从一次运行到下一次运行的行为。
如果人们说C ++是一种“不安全”的语言,那么这就是他们的意思的一部分。 C ++不会在运行时检查范围,因为这样做是运行时需要额外的CPU指令,而C ++的部分设计原则是使它不比C慢。
您的编译器可能已经能够在编译时警告您(您是否使用编译器命令行选项为您提供尽可能多的警告?),尽管语言无法保证/要求