-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++

4

3 回答 3

7

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

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

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

于 2013-02-08T20:47:59.510 回答
3

C++ 是一种为性能而编写的语言。如果您有一个包含 1000 万个项目的数组,并且合法地遍历所有项目,则将增加时间来检查这 10M 访问中的每一个是否有效。作为副作用,您还可以在“正确”的情况下走出有效范围而不会被检测到。最有可能的是,如果您超出有效范围太远,就会出现问题。但是 C++ 不能保证它确实会出错,或者可能发生什么其他事情——这就是所谓的“未定义行为”——简称 UB。

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

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

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

每当您超出有效范围时,这都会“破坏”您的程序。在发布版本中,assert编译为空,因此当您在正确的发布版本中运行代码时没有额外的代码。

于 2013-02-08T21:16:55.987 回答
0

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

于 2013-02-08T20:53:32.347 回答