我是C ++的新手,当我实现一个标记类时,遇到了运行时错误。 在调试时我发现运行时错误是由递增指针(**)attrib_list引起的,但另一个指向相同内存地址的指针在递增时不会产生错误, 请向我解释这种奇怪行为的原因是什么? 我使用hackerrank online ide来编译这段代码
class Tag{
public:
Tag():
tagname{""}, sz{0}, t_sz{0}, attrib_list{nullptr}, ptr_nav{nullptr}{
}
Tag(string name, int n_att):
tagname{name}, sz{0}, t_sz{n_att}, attrib_list{new string*[n_att]}{
for(int i=0; i<n_att; i++){
attrib_list[i] = new string[2];
}
ptr_nav = &attrib_list[0]; //take risk here
}
~Tag(){
for(int i=0; i< t_sz; i++){
delete[] attrib_list[i];
}
attrib_list = nullptr;
ptr_nav = nullptr;
t_sz, sz = 0;
}
// this function produces rintime error
void add_attribute(string name, string value){
(*attrib_list)[0] = name;
(*attrib_list)[1] = value;
sz++;
attrib_list++;
}
/*
This does not produce any error, why ????
void add_attribute(string name, string value){
(*ptr_nav)[0] = name;
(*ptr_nav)[1] = value;
sz++;
ptr_nav++;
}
*/
private:
string tagname;
string **attrib_list, **ptr_nav;
int sz, t_sz;
};
int main() {
Tag t("tag1", 2);
t.add_attribute("value1", "1"); //runtime error
t.add_attribute("value2", "2"); //runtime error
return 0;
}
答案 0 :(得分:0)
两次调用add_attribute
后,attrib_list
增加两次,现在指向原始new[]
- 已分配数组的末尾。这本身并不是问题。
但是当你的Tag
实例超出范围时,它的析构函数会运行并尝试在现在无效的attrib_list[i]
指针上访问attrib_list
,这当然会显示未定义的行为。
与直接问题无关:t_sz, sz = 0;
不会将0分配给两个变量(您似乎相信),但仅限于sz
。阅读您最喜欢的C ++参考中的逗号运算符。在任何情况下,你都不需要首先做到这一点(也不要将两个指针设置为nullptr
) - 无论如何它们都将被销毁,那时它们的价值并没有消失。无所谓。