C ++ - 需要帮助理解删除功能

时间:2016-04-16 22:58:55

标签: c++ memory-leaks delete-operator

我在理解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

4 个答案:

答案 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()方法,您还可以确定向量的当前长度,并且不再需要您的成员capacitysize

答案 2 :(得分:1)

内存泄漏不会导致任何内容无效。恰恰相反,它是一个无法使内存位置无效,导致它仍然在使用,即使它不应该使用。

答案 3 :(得分:1)

首先,当你delete某事时,你并没有在内存中摧毁它,只是让它可用于进一步的分配。这有点类似于文件系统 - 当您删除文件时,您只需说它占用的空间现在可用于某些新数据。在对它们调用delete之后,您实际上可以检索未修改的数据,但这是未定义的行为,并且将是编译器/操作系统特定的。

如果您不delete[] arrNames,则会将其数据遗忘在进程内存中,并造成内存泄漏。但除了这个致命的缺陷之外,没有更多的魔法发生了。