开发者

A few memory management questions involving class destructors and delete operator?

开发者 https://www.devze.com 2023-03-18 06:11 出处:网络
After reading some tutorials I am still unclear on some points about memory management in C++. 1. when a class declared with the new operator goes out of scope is its destructor called and memory fre

After reading some tutorials I am still unclear on some points about memory management in C++.

1. when a class declared with the new operator goes out of scope is its destructor called and memory freed? Is it necessary to call the delete operator to free the class' memory and have its destructor called?

class Test{};

void newTest(){
    Test *t = new Test;
}

int main()
{
    newTest();
    return 0;
}

2. Are variables (such as a vector) declared with the new keyword freed when the class they reside within is destroyed? Do those variables have to be explicitly deleted in the class's destructor?

class Test{
    vector<int> *vec;
public:
    Test();
};

Test::Test(){
    *vec = new vector<int>;
}

void newTest(){
    Test t;
}

int main()
{
    newTest();
    return 0;
}

3. Same as question 2, but with normal variables declared on the stack. In the following example, is the vector vec deleted when t goes out of scope?

开发者_运维技巧
class Test{
    vector<int> vec;
};

void newTest(){
    Test t;
}

int main()
{
    newTest();
    return 0;
}

4. Finally, which is the better way to declare a vector in a class, normally (on the stack) or with the new keyword (on the heap)?


It sounds like you may come from a Java background, so things with new work a bit differently in C++.

  1. The memory allocated with new must be explicitly destroyed with delete. This example has a memory leak.

  2. Similar to question 1, you must delete the memory in the class destructor to reclaim it.

  3. In this case the vector will be destructed automatically.

  4. Within a class, always prefer to store members by value (as opposed to with new) unless you have a specific reason to do otherwise. Just because it's stored by value within the class doesn't mean it's on the stack, it's in the same region of memory that the containing class occupies.

Finally note that in C++ you can use RAII to make memory management much less error prone. Take a look at shared_ptr, scoped_ptr, and unique_ptr for example. These all handle automatically freeing the newly allocated memory when appropriate.


  1. No, the destructor is not called and the memory is not freed. you have to delete the object.
  2. No, the variables are not freed. You have to delete them in the destructor.
  3. Yes, vec is deleted (the destructors are called and the memory is freed).
  4. Usually on the stack is better, when possible. It may not be possible if, for example, the ownership of the object is passed to another object. Also, one should not allocate too much memory on the stack (the OS has limits on this), in which case the object should be allocated on the heap.


  1. No, an object created using new is not automatically destroyed when your pointer goes out of scope. You need to explicitly delete any such object.
  2. Same answer. Any memory allocated with new must be freed explicitly. Most well-written classes will do this for you in the destructor. If you are writing the class, make sure you clean up any memory the class uses.
  3. This object is destroyed automatically for you. And, if it is well written, it will automatically destroy any memory it allocates.
  4. Most class instances should be allocated as local variables since this will ensure they are cleaned up automatically for you. However, if you need them globally or as part of a class, you'll need to declare them appropriately.


You should prefer to say an object has dynamic storage instead of "being on the heap". Similarly, use "automatic storage" instead of "on the stack".

The former are actually used in the standard, while the latter are more colloquial.

If an object has automatic storage then the compiler will automatically call its destructor when the object goes out of scope (at the end of the containing block).

The memory allocated with new needs to be explicitly released. The storage for the actual pointer will be reclaimed, but not the object it points to.

So, if you use new you need to have a matching delete. A new[] needs to be matched by a delete[].

(A "smart pointer" quite useful, as it will help relieve you of having to keep track of the new and delete's. Look it up!).

Destroying a vector (either via delete if allocated with new, or when it leaves scope if auto) will call the destructor of its elements. This is why it should we the preferred way to held multiple objects.

Conclusion:

If possible try to use smart pointers or collections. Otherwise, make sure you delete what you new. (And if you write a class, allocate in the constructor any dynamic members and delete them in the class' destructor.)


  1. when a class declared with the new operator goes out of scope is its destructor called and memory freed? Is it necessary to call the delete operator to free the class' memory and have its destructor called?

First some terminology:

A variable is either an object or a pointer (A clas is not declared with a new pointer).
Objects are automatically destroyed when they go out of scope.
Pointers are NOT deleted automatically.

Second prefer obejcts to pointers

void newTest()
{
    Test t;  // t created here and automatically destroyed.
}

Third. If you must create a pointer. Put it inside a smart pointer.

void newTest()
{
    std::auto_ptr<Test> t(new Test());  // t created here and automatically destroyed.
                                        // Which will call delete on the contained pointer.
}

Answer Question 1:

The pointer you declare goes out of scope but the memory is destructor is not called and the memory is leaked. You would need to do it manually (or use one of the techniques I pointed out).

  1. Are variables (such as a vector) declared with the new keyword freed when the class they reside within is destroyed? Do those variables have to be explicitly deleted in the class's destructor?

Terminology

You mean pointers initialized with new rather then declared with the new keyword

Answer to Question 2.

No. You must manually call destroy in the destructor. But it is better not to have a pointer in the class. Rather declare a vector object inside the class then it will be automatically destroyed.

class Test
{
    vector<int>                   vectorObject;
    std::auto_ptr<vector<int> >   vectorPtrInSmartPointer;
    vector<int>*                  vectorRaw
public:
    Test();
    ~Test();
private:
    Test(Test const& copy);
    Test& operator=(Test const& copy);
};

Test::Test()
   : vectorPtrInSmartPointer(new vector<int>())  // Need to initialize the smart pointer.
   , vectorRaw(new vector<int>)                  // Need to initialize the RAW pointer
{
   // Note the vectorObject was automatically created.
}
Test::~Test()
{
   delete vectorRaw;                             // Need to manually release the RAW pointer.
}
// Smart pointer and object auto released.

Note: Because the class Test contains a RAW pointer (vector*) I had to manually disable the copy constructor Test::Test(Test const&) and assignment operator Test& operator=(Test const&). This is to make sure the Rule of 3 is being followed.

  1. Same as question 2, but with normal variables declared on the stack. In the following example, is the vector vec deleted when t goes out of scope?

Yes.

  1. Finally, which is the better way to declare a vector in a class, normally (on the stack) or with the new keyword (on the heap)?

Calling it the stack/heap obscures the details (as a member may an automatic member of dynamically allocated object). Prefer to think of them as automatic variablesand dynamic variables. The automatic variables are autoamtically destroyed when their containing scope is destroyed. So for function variables this mean when you leave the function. For class members this means when the object is destroyed. The choice would be to prefer be to use automatic variables (ie not to allocate with new).


These two simple rules should answer all the questions:

  1. You should have as delete in your code as many as new.
  2. Prefer allocating from stack whenever possible instead of heap.
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号