2013-02-08 55 views
-1

我从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

有趣的是,PHP的表现比C++更严格。 – 2013-02-08 20:48:57

+1

在C++'operator [](keytype)中,如果map中没有一个已经存在,那么map *将会添加一个默认构造的map的value-type实例。如果你不想要这种行为,可以使用'.find(keytype)'来代替'my_map.end()'来检查生成的迭代器。 – WhozCraig 2013-02-08 20:49:18

+1

'句子[34535]'超出界限,并会导致程序崩溃。 – Rapptz 2013-02-08 20:50:41

回答

7

因为PHP和C++是两种截然不同的语言,它们具有完全不同的语义。在C++中将[]运算符与std::map对象一起使用时,如果密钥尚未存在于映射中,则会将新元素插入到映射中。在PHP中,情况并非如此。

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

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

0

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

3

C++是一种为提高性能而编写的语言。如果您拥有一个拥有1000万件物品的阵列,并合法地遍历所有物品,则会增加时间来检查这10M接入点中的每一个是否有效。作为一个副作用,你也可以在“正确”的情况下走出有效范围,而不会被发现。最有可能的是,如果你在有效范围之外太远,SOMETHING会出错。但是C++并不能保证它确实出错或者会发生什么 - 这就是所谓的“未定义行为” - 简称UB。

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

因此,如果您有“未知”索引 - 例如将索引作为参数的函数,最好检查该值是否在范围内 - 至少在代码的调试版本中。您可以使用例如assert()做到这一点:

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

这将“打破”你的节目你去超出有效范围的任何时间。在发布版本中,assert编译为无,因此在正确的发行版本中运行代码时没有额外的代码。

相关问题