c++ - 删除动态数组会导致运行时错误
问题描述
好的,所以我有这个关于 c++ 的作业问题并删除了一个动态数组。当我运行该程序时,它向我显示以下内容:http: //prntscr.com/p015e9 我猜问题出在删除指针上,因为我将其追踪到这些行:
delete[] _elementi1; _elementi1 = nullptr;
delete[] _elementi2; _elementi2 = nullptr;
这是我的课,当我调用“Dodaj”函数时发生错误
template<class T1, class T2 = int>
class FITKolekcija {
T1 * _elementi1;
T2 * _elementi2;
int _trenutno;
public:
FITKolekcija() {
_elementi1 = nullptr; // Elements 1 pointer
_elementi2 = nullptr; // Elements 2 pointer
_trenutno = 0; // This is the _current variable and is used as an iterator
}
~FITKolekcija() {
try {
delete[] _elementi1; _elementi1 = nullptr;
delete[] _elementi2; _elementi2 = nullptr;
}
catch (exception& e) {
cout << e.what() << endl;
}
}
T1 * GetT1() { return _elementi1; }
T2 * GetT2() { return _elementi2; }
int GetTrenutno() { return _trenutno; }
friend ostream& operator<< (ostream &COUT, FITKolekcija &obj) {
for (size_t i = 0; i < obj._trenutno; i++)
COUT << obj._elementi1[i] << " " << obj._elementi2[i] << endl;
return COUT;
}
void Dodaj(T1 clan1, T2 clan2) {
T1 *temp1 = new T1[_trenutno + 1];
T2 *temp2 = new T2[_trenutno + 1];
for (size_t i = 0; i < _trenutno; i++) {
temp1[i] = _elementi1[i];
temp2[i] = _elementi2[i];
}
delete[] _elementi1; _elementi1 = nullptr; // Here lies the runtime error
delete[] _elementi2; _elementi2 = nullptr;
temp1[_trenutno] = clan1;
temp2[_trenutno] = clan2;
_elementi1 = temp1;
_elementi2 = temp2;
_trenutno++;
//
}
}
使用以下代码,我可以在运行时错误发生之前执行 7 次“Dodaj”,如下所示:
int main() {
int v6 = 6, v13 = 13, v32 = 32, v63 = 63, v98 = 98, v109 = 109, v196 = 196;
FITKolekcija<int, int> numbers;
cout << "1" << endl;
numbers.Dodaj(v196, v6);
cout << "2" << endl;
numbers.Dodaj(v13, v32);
cout << "3" << endl;
numbers.Dodaj(v98, v196);
cout << "4" << endl;
numbers.Dodaj(v63, v13);
cout << "5" << endl;
numbers.Dodaj(v98, v196);
cout << "6" << endl;
numbers.Dodaj(v196, v6);
cout << "7" << endl;
return 0;
}
解决方案
首先,让我向您推荐一本好的 C++ 书籍。StackOverflow 不是学习基础知识的最佳场所。
指针是一个盒子。在这个盒子里,你可以放一张纸,上面写着一个地址。当你有一个指针时,它通常不与任何现有对象相关联(没有存储在框中的地址):
int my_p;
my_p
--------
| NULL |
--------
当您使用 时new
,您可以在某处获得指向某个真实对象的指针(您在某处建造一座真实建筑物并写下它的地址)。
my_p = new int[5];
my_p
----------
| 0x2358 |
----------
0x2358 0x2359 0x2360 0x2361 0x2362
-------- -------- -------- -------- --------
| 0 | | 0 | | 0 | | 0 | | 0 |
-------- -------- -------- -------- --------
您可以随意编辑指针指向的对象(您知道地址,您可以去建筑物并在那里粉刷墙壁):
my_p[2] = 13;
my_p
----------
| 0x2358 |
----------
0x2358 0x2359 0x2360 0x2361 0x2362
-------- -------- -------- -------- --------
| 0 | | 0 | | 13 | | 0 | | 0 |
-------- -------- -------- -------- --------
现在,当你复制一个指针时,你只复制了一个指针,而不是它指向的对象(你得到一个新的盒子并将相同的地址放在这个盒子里):
int* my_p2 = my_p;
my_p my_p2
---------- ----------
| 0x2358 | | 0x2358 |
---------- ----------
0x2358 0x2359 0x2360 0x2361 0x2362
-------- -------- -------- -------- --------
| 0 | | 0 | | 13 | | 0 | | 0 |
-------- -------- -------- -------- --------
my_p2
具有完全相同的属性my_p
并且它指向完全相同的对象my_p
(有任何一个盒子,你可以去房子并在那里放置地毯):
my_p2[3] = 26;
my_p
----------
| 0x2358 |
----------
0x2358 0x2359 0x2360 0x2361 0x2362
-------- -------- -------- -------- --------
| 0 | | 0 | | 13 | | 26 | | 0 |
-------- -------- -------- -------- --------
std::cout << my_p[3]; // prints 26, even though you used my_p2
当你delete
成为一个对象时,它会被标记为免费供编译器再次使用。(您获取地址并摧毁该地址的建筑物)。请注意,您无法保证该内存中的内容 - 从现在开始,它绝对可以是任何东西。
delete[] my_p;
my_p my_p2
---------- ----------
| 0x2358 | | 0x2358 |
---------- ----------
0x2358 0x2359 0x2360 0x2361 0x2362
-------- -------- -------- -------- --------
| FREE | | FREE | | FREE | | FREE | | FREE |
-------- -------- -------- -------- --------
但是指针本身并没有改变!他们仍然指向记忆中的相同位置(你摧毁了房子,但盒子在其他地方仍然是安全的,没有人在这些盒子里装过任何东西)。
这就是我们所说的悬空指针。如果您现在尝试使用此类指针指向的对象,您会得到未定义的行为(您带来了油漆和画笔并去了给定的地址,但没有房子可以油漆,或者更糟糕的是 - 其他人已经在那里建造了他们的房子!)
std::cout << my_p2[2]; //can format your C drive if it wishes to do so
推荐阅读
- c# - 为什么不能将 Console.ReadKey() 放在显示到控制台的文本前面,或者将 Console.ReadKey() 分配给变量?
- bazel - 如何使用 java_common.compile.annotation_processor_additional_outputs 生成声明的文件和目录?
- discord.js - DiscordJS 后门命令
- reactjs - json.stringify 无法序列化反应本机中的循环结构
- java - 有没有一种很好的方法来使用流过滤列表并获取项目列表,如果没有项目通过过滤器,则为 null?
- python - 如何覆盖嵌套的“点”运算符?
- swift - CloudKit 保存尝试对成员 'save(_:completionHandler:)' 的模糊引用
- javascript - 从复制到剪贴板的字符串中删除奇怪的字符
- symfony - Sonata Admin:如何更改表单内字段的最终视图
- flutter - 在小部件构建期间如何在颤动中导航?