C ++中的矢量范围

时间:2009-09-15 23:33:45

标签: c++

这里有另一个快速问题,我有这段代码:

  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处崩溃吗?

感谢。

4 个答案:

答案 0 :(得分:11)

访问向量的末尾是未定义的行为。什么事情都可能发生。您可能有nasal demons

答案 1 :(得分:5)

您的应用程序不会崩溃,因为有一些标准指定它应该崩溃。崩溃只是随机(未定义)行为。当你发现超出数组范围时,你不会总是遇到崩溃。

基本上,任何事情都可能发生,例如打印空行,崩溃甚至刚发布 - 让恶魔飞出你的鼻子。

答案 2 :(得分:5)

你有一个只有六个元素的数组。当您尝试访问所谓的“第七”元素时,您将获得未定义的行为。从技术上讲,这意味着任何事情都可能发生,但在我看来,这似乎不是一个非常有用的解释,所以让我们仔细看看。

该数组占用内存,当您访问元素超出结束时,您正在读取占用该内存的任何值。 可能该地址不属于您的进程,但它可能是,因此读取驻留在该空间中的sizeof(string)字节通常是安全的。

您的程序从中读取,并且由于它是通过string数组读取的,因此它将该内存视为真正的string对象。 (你的程序无法区分它。它不知道更好。它只是试图执行你的指示。)显然,无论发生什么数据都看起来像一个真正的string对象,你的程序能够像对待它一样,至少足够长,以便在vector中复制它,然后打印它的(空)值。这次工作有效,但这并不意味着它每次都会起作用。

阵列的“第八”位置的数据没有运气。它看起来不像有效的string对象。 string对象通常包含指向字符数据的指针以及长度。也许通常代表该指针的对象区域不包含程序的有效地址。或者,表示长度字段的部分可能包含的值远远大于指针中地址的可用值。

答案 3 :(得分:2)

C ++不对数组进行范围检查。

超出数组末尾的读取是所谓的“未定义”行为:即不能保证抛出异常,不保证抛出异常,并且不能保证一致从一次运行到下一次运行的行为。

如果人们说C ++是一种“不安全”的语言,那么这就是他们的意思的一部分。 C ++不会在运行时检查范围,因为这样做是运行时需要额外的CPU指令,而C ++的部分设计原则是使它不比C慢。

您的编译器可能已经能够在编译时警告您(您是否使用编译器命令行选项为您提供尽可能多的警告?),尽管语言无法保证/要求