2

I am dynamically allocating memory for an array in a function. My question is: once the function finishes running is the memory freed?

code:

void f(){
    cv::Mat* arr = new cv::Mat[1];
    ...
}
Aly
  • 15,865
  • 47
  • 119
  • 191
  • I'm fixing the problem by not using heap. – tp1 Nov 02 '12 at 16:11
  • 2
    General rule: exactly one `delete` for each `new`, exactly one `delete[]` for each `new[]`. – Robᵩ Nov 02 '12 at 16:22
  • 2
    Or better yet... all calls to new assigned to a smart pointer and *no* explicit calls to delete! ;) –  Nov 02 '12 at 17:01
  • @BleepBloop Can you please explain what a smart pointer is? – Aly Nov 02 '12 at 17:55
  • @Aly See my response. Smart pointers (look up `unique_ptr` and `shared_ptr` are classes that act like pointers, but also automatically delete their memory when they go out of scope. – Matt Kline Nov 02 '12 at 18:21
  • Here is a related question about smart pointers which might help: http://stackoverflow.com/questions/395123/raii-and-smart-pointers-in-c –  Nov 03 '12 at 18:15

5 Answers5

6

No, memory allocated using new is not automatically freed when the pointer goes out of scope.

However, you can (and should) use C++11's unique_ptr, which handles freeing the memory when it goes out of scope:

void f(){
    std::unique_ptr<cv::Mat[]> arr(new cv::Mat[1]);
    ...
}

C++11 also provides shared_ptr for pointers you might want to copy. Modern C++ should strive to use these "smart pointers", as they provide safer memory management with almost no performance hit.

Matt Kline
  • 10,149
  • 7
  • 50
  • 87
  • no C++11 for me :(, I installed gcc using apt-get which I assumed would give me the latest and greatest but it appears unique_ptr does not exist for me – Aly Nov 02 '12 at 16:20
  • 2
    @Aly, When you invoke `g++`, try `g++ -std=c++11` or `g++ -std=c++0x`. One of these should enable `unique_ptr`. – Robᵩ Nov 02 '12 at 16:24
4

No, it is not. You must free it by calling

delete[] arr;

But you should ask yourself whether it is necessary to allocate dynamically. This would require no explicit memory management:

void f(){
    cv::Mat arr[1];
    ...
}

If you need a dynamically sized array, you could use an std::vector. The vector will internally allocate dynamically, but will take care of de-allocating it's resources:

void f(){
    std::vector<cv::Mat> arr(n); // contains n cv::Mat objects
    ...
}
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • However, you also can't dynamically size the array (at least within the C++ standard - I know gcc provides dynamically-sized arrays as an extension). – Matt Kline Nov 02 '12 at 16:13
  • @slavik262 Thanks. I added an example with `vector`. Although OP's example uses the compile time constant `1`. – juanchopanza Nov 02 '12 at 16:18
4

No. Every call to new needs to be matched up with a call to delete somewhere.

In your case arr iteself is a variable with automatic storage duration. This means that arr itself will be destroyed when it goes out of scope. However the thing that arr points to does not, because that is a variable that does not have autoatic storage duration.

The fact that arr itself has automatic storage duration can be used to your advantage, by wrapping the raw pointer in a class that destroys the stored pointer when the automatic object is destroyed. This object utilizes an idion known as RAII to implement a so-called "smart pointer". Since this is a very common requirement in well-designed applications, the C++ Standard Library provides a number of smart pointer classes which you can use. In C++03, you can use

std::auto_ptr

In C++11 auto_ptr has been deprecated and replaced by several other better smart pointers. Among them:

std::unique_ptr std::shared_ptr

In general, it is a good idea to use smart pointers instead of raw ("dumb") pointers as you do here.

If what you ultimately need are dynamically-sized arrays, as supported by C99, you should know that C++ does not have direct support for them. Some compilers (notably GCC) do provide support for dynamically sized arrays, but these are compiler-specific language extensions. In order to have something that approximates a dynamically sized array while using only portable, Standards-compliant code, why not use a std::vector?

Edit: Assigning to an array:

In your comments you describe the way in which you assign to this array, which I have taken to mean something like this:

int* arr = new int[5];
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;

If this is the case, you can accomplish the same using vector by calling vector::operator[]. Doing this looks uses very similar syntax to what you've used above. The one real "gotcha" is that since vectors are dyanamically sized, you need to make sure the vector has at least N elements before trying to assign the element at position N-1. This can be accomplished in a number of ways.

You can create the vector with N items from the get-go, in which case each will be value-initialized:

vector<int> arr(5); // creates a vector with 5 elements, all initialized to zero
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;

You can resize the vector after the fact:

vector<int> arr; // creates an empty vector
arr.resize(5); // ensures the vector has exactly 5 elements
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;

Or you can use a variety of algorithms to fill the vector with elements. One such example is fill_n:

vector<int> arr; // creates empty vector
fill_n(back_inserter(arr), 5, 0);  // fills the vector with 5 elements, each one has a value of zero
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;
John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • Hi, I am not using a vector because I am assigning to the array in a random manner. i.e if array is size 5 I may set arr[3] followed by arr[1] etc. when I tried this with vectors it just terminated the program with no exception :(. I don't appear to have C++11 can you please provide a code sample to use std::auto_ptr (I'm very new to c++). – Aly Nov 02 '12 at 16:23
  • 1
    @Aly: You can assign to a `vector` as you have described, if I understand you correctly. See my edit. – John Dibling Nov 02 '12 at 16:50
1

No, of course not.

For every new you need precisely one delete.

For every new[] you need precisely one delete[].

Since you don't have the matching delete[], your program is broken.

(For that reason, the adult way of using C++ is not to use new or pointers at all. Then you don't have those problems.)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    "For that reason, the adult way of using C++ is not to use new or pointers at all. Then you don't have those problems." What? Are you suggesting to never use the heap? – Matt Kline Nov 02 '12 at 16:12
  • @slavik262: Of course not. But I'm strongly encouraging not to use the so-called heap **manually**! Library functions are better at that, and safer. – Kerrek SB Nov 02 '12 at 16:16
  • Using `new` is certainly fine if you wrap it in C++11 smart pointers - there's plenty of instances where you would need to allocate your own memory outside of a library you're using. – Matt Kline Nov 02 '12 at 16:18
  • @JohnDibling: Just for reasons of exception safety alone, `new` calls should go into a very restricted set of auxiliary functions such as `make_unique`. – Kerrek SB Nov 02 '12 at 16:26
  • 1
    @KerrekSB: Setting aside the pedantry of there being no `make_unique` in the Standard Library, I don't disagree. – John Dibling Nov 02 '12 at 16:58
1

No. The array the allocated on the heap, you'll have to delete it before it goes out of scope:

void f() {

    cv::Mat * arr = new cv::Mat[1];

    // ...

    delete [] arr;

}
David G
  • 94,763
  • 41
  • 167
  • 253
  • New C++ code should try to avoid using `delete` explicitly - `unique_ptr` and `shared_ptr` do it automatically and provide better ownership semantics. – Matt Kline Nov 02 '12 at 16:14