我在理解C ++中的delete和delete []函数时遇到了麻烦。这是我目前所知道的:
aClass *ptr = new aClass(); //Allocates memory on the heap for a aClass object
//Adds a pointer to that object
...
delete ptr; //ptr is still a pointer, but the object that it
//was pointing to is now destroyed. ptr is
//pointing to memory garbage at this point
ptr = anotehrOjbectPtr //ptr is now pointing to something else
如果发生这种情况,
aClass *ptr new aClass();
...
ptr = anotherObjectPtr
指针指向的对象现在在内存中丢失,这将导致内存泄漏。该对象应该先被删除。
我希望以上是正确的
但我写了这个小程序,我得到了一些意想不到的行为
#include <iostream>
#include <string>
using namespace std;
class Database {
private:
Database() {
arrNames = NULL;
capacity = 1;
size = 0;
}
Database(const Database &db) {}
Database &operator=(const Database &db) {}
string *arrNames;
int capacity, size;
public:
static Database &getDB() {
static Database database;
return database;
}
void addName(string name) {
if (arrNames == NULL) {
arrNames = new string[capacity];
}
if (size == capacity - 1) {
capacity *= 2;
string *temp = new string[capacity];
int i = 0;
while (i <= size) {
temp[i] = arrNames[i];
i++;
}
delete [] arrNames;
arrNames = temp;
}
arrNames[size] = name;
size++;
}
void print() {
int i = 0;
while (i <= size) {
cout << arrNames[i] << endl;
i++;
}
}
};
int main() {
Database &database = Database::getDB();
Database &db = Database::getDB();
Database &info = Database::getDB();
database.addName("Neo");
db.addName("Morpheus");
info.addName("Agent Smith");
database.print();
db.print();
info.print();
}
在addName函数中,当我调用delete [] arrNames时,我认为发生的事情是与当前数组arrNames关联的内存被破坏,因此arrNames现在指向垃圾,然后arrNames被指向另一个temp指向的内存中的位置。因此,如果我没有调用delete [] arrNames,那么内存中的该位置将无效,从而导致内存泄漏。但是,当我注释掉该行时,代码仍然可以正常工作。我在这里不明白吗?
很抱歉这个si太久了 感谢halp
答案 0 :(得分:4)
然而,当我注释掉那一行时,代码仍然没有问题。我在这里不明白吗?
关于编程的一个重要事项是,正确地做事不仅仅是让事情看起来有效。
很多时候,你可以尝试一些东西看起来有效,但是一些外部环境会发生变化,你没有明确地控制或解释,而事情就会停止工作。例如,您可能编写一个程序,它在您的计算机上运行find,然后您尝试将其演示给某人并碰巧在他们的计算机上运行它,程序崩溃了。这个想法是程序员之间开玩笑的基础:&#34;它对我有用。&#34;
所以事情可能会起作用,但为了知道即使条件发生变化,事情也会有效,你必须达到更高的标准。
你已经被告知如何使用delete
正确地做事,但这并不一定意味着如果你不这样做,事情会以明显的方式破裂。你需要放弃一个想法,即你可以通过尝试来明确地确定某些事情是否正确。
答案 1 :(得分:3)
从我在代码中看到的情况来看,addName()
似乎是要将新名称附加到动态数组上。自己这样做可能会让人头疼,而且我强烈建议使用vector
标题来建立一个方便的STL模板,我称之为<vector>
。
如果您添加#include <vector>
并将string *arrNames
更改为vector<string> arrNames
,那么您的整个addName()
功能可以缩减为:
void addName(string name){
arrNames.push_back(name);
}
通过vector.size()
方法,您还可以确定向量的当前长度,并且不再需要您的成员capacity
和size
。
答案 2 :(得分:1)
内存泄漏不会导致任何内容无效。恰恰相反,它是一个无法使内存位置无效,导致它仍然在使用,即使它不应该使用。
答案 3 :(得分:1)
首先,当你delete
某事时,你并没有在内存中摧毁它,只是让它可用于进一步的分配。这有点类似于文件系统 - 当您删除文件时,您只需说它占用的空间现在可用于某些新数据。在对它们调用delete
之后,您实际上可以检索未修改的数据,但这是未定义的行为,并且将是编译器/操作系统特定的。
如果您不delete[] arrNames
,则会将其数据遗忘在进程内存中,并造成内存泄漏。但除了这个致命的缺陷之外,没有更多的魔法发生了。