Resource Acquisition Is Initialization

From Schmid.wiki
Jump to: navigation, search

A RAII class should:

  • only have a single point of possible failure, in the constructor
  • the failure should result in an exception
  • all member variables should be RAII
  • have copying prevented to avoid handing over ownership of resource to another object

Example

#include <iostream>
#include <fstream>
using namespace std;

class File_resource {
public:
    class error {};
    File_resource(const char *name) throw(error) : file(name) {
        cerr << "File_resource ctor started\n";
        if(not file.good()) throw error(); // may fail
        cerr << "File_resource ctor done\n";
    }
    ~File_resource() { cerr << "File_resource dtor\n"; }
private:
    // prevent copying
    File_resource(const File_resource&);
    File_resource& operator=(const File_resource&);

    // ifstream is pseudo-RAII, the object may be constructed, even though
    // resource allocation fails
    ifstream file;
};
class Memory_resource {
public:
    Memory_resource(unsigned int size) throw(bad_alloc) {
        cerr << "Memory_resource ctor started\n";
        data = new int[size]; // may fail
        cerr << "Memory_resource ctor done\n";
    }
    ~Memory_resource() {
        cerr << "Memory_resource dtor\n";
        delete[] data;
    }
private:
    // prevent copying
    Memory_resource(const Memory_resource&);
    Memory_resource& operator=(const Memory_resource&);

    int *data;
};
class Resource_group {
public:
    Resource_group(const char *name, unsigned int memory)

        // member variables are initialized in the order in which they are
        // declared, i.e. memory_resource, then file_resource
        : file_resource(name), memory_resource(memory) {

        cerr << "Resource_group ctor done\n";
    }
    ~Resource_group() { cerr << "Resource_group dtor\n"; }
private:
    // prevent copying
    Resource_group(const Resource_group&);
    Resource_group& operator=(const Resource_group&);

    Memory_resource memory_resource;
    File_resource   file_resource;
};

int main(void) {
    try {
        Resource_group rg("test.cppas", 10000);
    }
    catch(bad_alloc)            { cerr << "* bad allocation!\n"; }
    catch(File_resource::error) { cerr << "* file error!\n";     }
}

If the program is successful, it outputs:

Memory_resource ctor started
Memory_resource ctor done
File_resource ctor started
File_resource ctor done
Resource_group ctor done
Resource_group dtor
File_resource dtor
Memory_resource dtor

If memory allocation fails, it outputs:

Memory_resource ctor started
* bad allocation!

If file opening fails, it outputs:

Memory_resource ctor started
Memory_resource ctor done
File_resource ctor started
Memory_resource dtor
* file error!

References

Personal tools