0

I'm studying C++ now. It is a so complicated language that I'm not sure which feature I should use and when to use.

C++ Primer introduces RAII as a method to ensure exception safety. Does that mean, as a good behavior, when I want to use an array, I should put array into an class to allocate and destroy resources. I know my idea is very simple, or naive.

I'm just curious about what is good C++ coding behavior.

yuanqili
  • 392
  • 3
  • 12

3 Answers3

5

RAII means that a resource is tied to the object lifetime.
Every STL class of C++ follows this principle, this means that if you need an array you can simply use std::vector.

The destructor of the vector class will take care of deleting the resources when your instance goes out of the scope.

This means that in your case, instead of using new like this:

int *array = new int[n];

you should use:

vector<int> array(n);

If you really need to allocate on the heap to have a shared pointer and still be safe by using RAII you can do (requires C++11):

shared_ptr<vector<int>> array(new vector<int>(10));
dynamic
  • 46,985
  • 55
  • 154
  • 231
2

It depends how you create your array. If you create it in some block of code like this

int arr[5];

it has automatic storage. This array is automatically destroyed when it goes out of scope.

The only time you have to explicitly manage the lifetime of your objects is if you dynamically allocate them, perhaps like so:

int* arr = new int[5];

This allocates an array of 5 ints which need to be manually deleted later like this:

delete[] arr;

RAII is the idea that we can have a class's constructor perform the dynamic allocation and its destructor perform the deallocation. Then if we create objects of this class type, they will internally perform dynamic allocation, but we can be sure that the memory will be correctly deallocated when finished with.

So yes, if you really want a dynamically allocated array, you could encapsulate it in your own class. However, this already exists in a more powerful form: std::vector. The std::vector type internally manages a dynamically allocated array, but also allows you to add elements to and remove elements from it at run-time.

Note that this isn't something specific to arrays. Best practice is to encapsulate all dynamic allocation (even a simple new int) within classes. The standard library provides many classes to help you do this (in particular, smart pointers).

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
1

RAII is a recommended idiom for resource management -- resources can be threads, memory... I frequently encounter long-time developers who don't understand RAII or how to use it, so there's no shame in asking. Unfortunately, I think you need a little background and terminology to understand it. In C++ you can create objects in one of two kinds of memory: The stack and the heap.

The Stack: Consider this code:

class Foo
{
    // some implementation
}

void bar()
{
  Foo f;
  // do something with f.
  // maybe it throws an exception, maybe not.
}

Here the object f of type Foo has been created on the stack. When the running program leaves the scope in which f was created (in our example when it leaves the function bar()), f's destructor will called, regardless of how it leaves the scope. It might leave scope because the function executed successfully, or it might leave scope because an exception was thrown.

Heap allocation Now consider the following:

class Foo
{
// same thing
}

void bar()
{
Foo* f = new f;
// whatever
delete f;
}

In this case we created the object f on the heap. You can tell we did so because we called the new operator. Whenever an object is created with new, we have to call delete in order to free the memory up. This can be error prone, because people forget to call delete, or they return the pointer and it's unclear where the pointer should get deleted, or because an exception is thrown. RAII is a solution to all those, and it should be your first tool of choice.

But that doesn't mean you should put your arrays in a class (well it kind of does in some circumstances, but probably not in the way that you mean). Consider the following:

void foo()
{
     // c-style array, but fixed size.
     int bar_stack[5];

     // c-style array, dynamically allocated!
     unsigned int array_size = get_array_size();
     int* bar_heap = new int[array_size]

     // c++ way:
     std::vector bar_vector(array_size);
 }

In the first example we have a fixed c-style array, it's allocated on the stack, so it's nothing to worry about. In the second case, it's dynamically allocated (the compiler doesn't know the size, its available at run time), so we would need a delete, meaning we'd need to protect against exceptions and make sure there's a clear owner. In the third case we just use a vector, which is a standard container.

Now I provided all that because I was afraid you wouldn't understand the short answer which is: Yes you should generally use RAII to manage your resources, but you should use std containers, not arrays. Why? Because std containers provide RAII for you -- unless you make a container of pointers, or allocate your vector on the heap.

I hope that helps.

Spacemoose
  • 3,856
  • 1
  • 27
  • 48
  • Thank you very much for your detailed instruction. I read Effective C++ tonight and found such ideas in that book. The reason I asked this question because I'm not sure the tradeoff, if there is it, between efficiency and safety. Thanks again :) – yuanqili Jan 31 '15 at 08:37