CS253: Software Development with C++

Spring 2023

RAII

Show Lecture.RAII as a slide show.

CS253 RAII

Worst Acronym Ever

RAII means:

Very Slightly Better

CADRE means:

Definition

Non-RAII code

Here’s some non-RAII code:

// Acquire resources
FILE *host = fopen("/etc/hostname", "r");
float *scores = new float[253];
char *name = new char[50];

// Use resources
cout << "hi there\n";

// Clean up after ourselves
delete[] name;
delete[] scores;
fclose(host);
hi there

RAII code

The equivalent RAII code:

// Acquire resources
ifstream host("/etc/hostname");
unique_ptr<float[]> scores(new float[253]);
string name(50, 'X');

// Use resources
cout << "hi there\n";

// Clean up after ourselves
hi there

Even better

Sure, unique_ptr does the job. This works fine:

unique_ptr<float[]> scores(new float[253]);
scores[5] = 70;
cout << scores[5];
70

However, vector works just as well, and reads a lot better:

vector<float> scores(253);
scores[5] = 70;
cout << scores[5];
70

So does array (for compile-time sizes):

array<float,253> scores;
scores[5] = 70;
cout << scores[5];
70

As does a plain old C array (for compile-time sizes):

float scores[253];
scores[5] = 70;
cout << scores[5];
70

Why RAII?

It’s not too difficult to remember to free our resources, but what if something gets in the way?

float *scores = new float[253];
if (getuid() != 0) {
    cerr << "Must be super-user!\n";
    return 1;       // Forgot to delete scores!
}
cout << "hello\n";
delete[] scores;
Must be super-user!

Sure, we could add delete[] scores to the if clause, but what if there are several early returns, and many variables? It’s not very DRY. Also, what about exceptions?

Why RAII?

unique_ptr<float[]> scores(new float[253]);
if (getuid() != 0) {
    cerr << "Must be super-user!\n";
    return 1;
}
cout << "hello\n";
Must be super-user!

This code isn’t bothered by early returns or exceptions. They will both cause the unique_ptr to be destroyed, and its dtor will free the memory.

Simplicity of Description

Consider this non-RAII code:

double *p;
// … region 1 …
p = new double[100];
// … region 2 …
delete[] p;
// … region 3 …
Describe p in the various regions.
  1. uninitialized, indeterminate
  2. pointing to 100 doubles
  3. indeterminate; probably a stale pointer to the ex-doubles

Simplicity of Description

Consider this RAII code:

unique_ptr<double[]> p(new double[100]);
// … region 1 …
Describe p in the various regions.
  1. pointing to 100 doubles

Gosh, that seems easier to understand.

Other Uses

Use RAII when you think “Don’t forget to …”, which might apply to:

Rule of Zero

Remember the Rule of Three? There’s also the Rule of Zero, which says, essentially:

Real-Life RAII

Real-Life RAII

a picture of a person wearing a gas mask