2016-04-16 38 views
1

我一直无法理解C++中的删除和删除[]函数。这是我目前所知:C++ - 需要帮助理解删除功能

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 

该指针指着,现在失去了在内存中的对象,ADN这将导致内存泄漏。该对象应该先被删除。

希望以上是正确的

但是我写了这个小程序,在那里我得到一些意外的行为

#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功能,当我打电话删除[] arrNames,什么我认为正在发生的事情是与当前数组arrNames关联的内存被销毁,所以arrNames现在指向垃圾,然后arrNames被指向指向temp指向的内存中的另一个位置。所以如果我没有调用delete [] arrNames,那么内存中的那个位置就会失效,导致内存泄漏。但是,当我将该行注释掉时,代码仍然没有问题。我在这里没有理解什么吗?

遗憾,这对这么久 感谢HALP

+1

当你注释掉哪一行?不删除某些内容不会使任何内容失效,它只是泄漏内存 - 在不应该的时候保持有效。 –

+0

*代码仍然可以正常工作* - 存在问题。您创建了一个未被发现的内存泄漏。 – PaulMcKenzie

+0

内存泄漏是指已分配的内存,但程序中没有指针指向它。如果你的代码在其他方面行为恰当,那么在你的程序中使用指针就可以正常工作。内存泄漏的问题在于,最终分配将开始失败,您将无法释放泄漏的内存来防止这种情况发生。 – Peter

回答

1

内存泄漏不涉及任何被无效。恰恰相反,这是一个失败的内存位置无效,导致它仍然在使用,即使它不应该。

3

从我认为在代码中看到的看起来addName()是为了将新名称追加到动态数组上。自己这样做可能会导致头痛,并且现在有一个方便的STL模板,我强烈建议从<vector>标头中调用vector。 如果添加#include <vector>和更改string *arrNamesvector<string> arrNames,那么你的整个addName()功能,可以简化为:

void addName(string name){ 
    arrNames.push_back(name); 
} 

vector.size()方法,你可以确定向量的当前长度,以及,你的成员capacitysize不再需要。

4

但是,当我注释掉该行时,代码仍然没有问题。我在这里没有理解什么吗?

关于编程知道一件重要的事情是,正确地做事不仅仅是让事情显然工作的问题。

很多时候,你可以尝试一些事情,看起来有什么作用,但随后一些外部环境会改变,你没有明确控制或考虑的事情,并且事情停止工作。例如,您可能会编写一个程序,并在您的计算机上运行查找,然后尝试将其演示给某人,并发生在计算机上运行该程序,并且程序崩溃。这个想法是程序员之间玩笑的基础:“它适合我。“

所以事情可能会出现的工作,但为了知道,当条件发生变化,你必须满足更高标准的东西会更加。

你已经被告知如何正确地做事情delete,但这并不一定意味着如果你不这样做,事情将会以明显的方式破裂,你需要放弃这样的想法,即你可以通过试验确定是否正确。

1

首先,当你有某种东西的时候,你并没有在内存中摧毁它,而只是将它提供给所有人ocation。这有点类似于文件系统 - 当你删除文件时,你只是说它占用的空间现在可用于一些新的数据。在您调用delete之后,您实际上可以检索未修改的数据,但这是未定义的行为,并且是编译器/操作系统特定的。

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