简体   繁体   English

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

[英]C++ - need help understanding the delete function

I've been having trouble understanding the delete and delete [] functions in C++. 我在理解C ++中的delete和delete []函数时遇到了麻烦。 Here's what I know so far: 到目前为止,这是我所知道的:

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

In the case that this happens, 如果发生这种情况,

aClass *ptr new aClass();
...
ptr = anotherObjectPtr 

the object that pointer was pointing to, is now lost in memory, adn this will cause a memory leak. 指针指向的对象现在已丢失在内存中,这将导致内存泄漏。 The object should've been deleted first. 该对象应先删除。

I hope the above is correct 我希望以上是正确的

But I wrote this small program, where I'm getting some unexpected behaviour 但是我写了这个小程序,在那里我遇到了一些意外的行为

#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();
}

In the addName function, when I call delete [] arrNames, what I think is happening is that the memory associated with the current array arrNames is destroyed, so arrNames is now pointing at garbage, Then arrNames is directed to point to another location in memory that is pointed to by temp. 在addName函数中,当我调用delete [] arrNames时,我认为正在发生的事情是与当前数组arrNames关联的内存已被破坏,因此arrNames现在指向垃圾,然后arrNames指向内存中的另一个位置。 temp指向的。 So if I hadn't called delete [] arrNames, then that location in memory would've been invalid, causing a memory leak. 因此,如果我没有调用delete [] arrNames,那么内存中的该位置将无效,从而导致内存泄漏。 However, when I comment out that line, the code still works without problems. 但是,当我注释掉这一行时,代码仍然可以正常工作。 Am I not understanding something here? 我在这里不明白吗?

Sorry that this si so long Thanks for the halp 抱歉,这么久才感谢您的帮助

However, when I comment out that line, the code still works without problems. 但是,当我注释掉这一行时,代码仍然可以正常工作。 Am I not understanding something here? 我在这里不明白吗?

An important thing to know about programming is that doing things correctly is not merely a matter of having things apparently work. 有关编程的一件重要事情是,正确地做事情不仅仅是使事情看起来正常的问题。

Often times you can try something out hand have things appear to work, but then some outside circumstances change, something you're not explicitly controlling or accounting for, and things stop working. 通常,您可以尝试一些尝试使事情看起来可行,但是随后某些外部环境会发生变化,您没有明确控制或解释的某些事情会停止工作。 For example you might write a program and it runs find on your computer, then you try to demo it to someone and happen to run it on their computer, and the program crashes. 例如,您可能编写了一个程序,并且该程序在计算机上运行find,然后尝试将其演示给某人并碰巧在他们的计算机上运行该程序,该程序崩溃了。 This idea is the basis of the running joke among programmers: "It works for me." 这个想法是程序员开玩笑的基础:“它对我有用。”

So things might appear to work, but in order to know that things will work even when conditions change you have to meet a higher standard. 因此,事情似乎可以正常工作,但是为了知道即使条件发生变化,事情也可以正常工作,您必须满足更高的标准。

You've been told how to do things correctly with delete , but that doesn't necessarily mean that things will break in an obvious way if you fail to do so. 有人告诉您如何使用delete正确执行操作,但这并不一定意味着如果不这样做,操作将以明显的方式损坏。 You need to abandon the idea that you can definitively determine whether something is correct or not by trying it out. 您需要放弃这样的想法,即可以通过尝试确定某些东西是否正确。

From what I think I see in your code, it looks like addName() is meant to append the new name onto the dynamic array. 根据我在您的代码中看到的内容,看起来addName()打算将新名称附加到动态数组上。 Doing this yourself can be headache inducing, and there is an existing convenient STL template for just this which I strongly recommend, called vector , from the <vector> header. 这种做自己可出现头痛诱导,并且对于眼前这个,我强烈建议,呼吁现有的方便STL模板vector ,从<vector>头。 If you add #include <vector> and change string *arrNames to vector<string> arrNames , then your entire addName() function can be reduced to: 如果添加#include <vector>并将string *arrNames更改为vector<string> arrNames ,则整个addName()函数可以简化为:

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

From the vector.size() method, you can determine the current length of the vector as well, and your members capacity and size are no longer needed. 通过vector.size()方法,您还可以确定向量的当前长度,并且不再需要成员的capacitysize

A memory leak doesn't involve anything being made invalid. 内存泄漏不会导致任何无效。 Quite the reverse, it's a failure to make a memory location invalid, causing it to remain in use even when it shouldn't be. 恰恰相反,这是使内存位置无效的一种失败,即使在不应使用的情况下也可以继续使用。

First of all, when you delete something, you are not destroying it in memory, just making it available for some further allocation. 首先,当您delete某些内容时,您并没有在内存中销毁它,只是将其用于其他分配。 This is somewhat similar to filesystem - when you delete file, you just say space it occupied is now available for some new data. 这有点类似于文件系统-删除文件时,您只是说它占用的空间现在可用于一些新数据。 You could actually retrieve unmodified data after you called delete on them, but this is undefined behavior and will be compiler/OS specific. 在调用未delete数据后,您实际上可以检索未修改的数据,但这是未定义的行为,将特定于编译器/ OS。

If you don´t delete[] arrNames , you leave its data forgotten in your process´s memory, and creating memory leak. 如果不delete[] arrNames ,则会将其数据遗忘在进程的内存中,并造成内存泄漏。 But beside this fatal flaw, there is no more magic happening. 但是除了这个致命的缺陷之外,没有其他魔术发生了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM