为什么我在使用未定义索引时没有收到错误?

时间:2013-02-08 20:46:06

标签: php c++ indexing

我来自php,当我定义这样的事情时:

$a = array();
echo $a[586];

我会收到有关未定义索引的通知。

同时在c++我可以这样做:

map<int, string> my_map;
cout << "Map is: " << my_map[34535];

string sentence = "acdefb s";
cout << "Letter is: " << sentence[15];

我不会有任何错误。

为什么php无效,c++无效?

3 个答案:

答案 0 :(得分:7)

因为PHP和C ++是两种截然不同的语言,语义完全不同。在C ++中使用[]运算符和std::map对象时,如果映射中不存在该键,则会将新元素插入到映射中。在PHP中,情况并非如此。

对于使用std::string sentance的第二个示例,使用带有无效索引的[]运算符 是有效的(索引是在C ++中的>= sentance.length()上是std::string)。您可能不会收到任何“错误”,因为使用std::string的无效索引的结果是 undefined behavior ,这意味着任何事情都可能发生。现代平台上的一个常见结果是分段错误/访问冲突,这通常会导致程序崩溃。

使用std::string,如果您希望防范未定义的行为,则可以使用std::string::at()而不是[]运算符。如果您使用无效索引,at函数会执行边界检查并抛出std::out_of_range

答案 1 :(得分:3)

C ++是一种为性能而编写的语言。如果你有一个包含1000万个项目的数组,并且合法地遍历所有项目,那么它将增加时间来检查这些10M访问中的每一个是否有效。作为副作用,你也可以在&#34;右边&#34;环境走出有效范围之外,没有被检测到。最有可能的是,如果你超出有效范围,SOMETHING就会出错。但C ++并不能保证它确实出错了,或者其他可能发生的事情 - 它被称为&#34;未定义的行为&#34; - UB简称。

对于地图,它不会做你认为它做的事情,它实际上在你的容器中创建一个新的空元素,然后打印出来。

因此,如果你有&#34;未知&#34; index - 例如,将索引作为参数的函数,检查值是否在范围内是个好主意 - 至少在代码的调试版本中。您可以使用例如assert()来执行此操作:

// v is a vector, or string, or some such. 
assert(index < v.size); 

这将&#34;打破&#34;当你超出有效范围时,你的程序。在发布版本中,assert编译为空,因此在适当的发布版本中运行代码时没有额外的代码。

答案 2 :(得分:0)

将句子字符串索引的值大于字符串的长度几乎总是会导致分段错误。如果这段代码实际上在没有错误的情况下运行,那是因为“幸运的是”这个内存地址不能解析为不属于该进程的东西。相反,你只会得到垃圾。