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