All notes
CppIdioms

RAII

Resource Acquisition Is Initialization.

Intent:

Problem

Resources acquired in a function scope should be released before leaving the scope unless the ownership is being transferred to another scope or object. For example, new/delete, malloc/free, lock.acquire/lock.release, file-open/file-close, nested_count++/nested_count--, etc.

It is too dangerous to trust the programmer that he or she will invoke resource release operation in all possible cases in the present and in the future.

Solution

The idea is to wrap the resource release operation in a destructor of an object in the scope.

Acquiring resource(s) in constructor is not mandatory in RAII idiom but releasing resources in the destructor is the key. Therefore, it is also known (rarely though) as Resource Release is Finalization idiom.


class NonCopyable 
{
   NonCopyable (NonCopyable const &); // private copy constructor
   NonCopyable & operator = (NonCopyable const &); // private assignment operator
};
template <class T>
class AutoDelete : NonCopyable
{
  public:
    AutoDelete (T * p = 0) : ptr_(p) {}
    ~AutoDelete () throw() { delete ptr_; } // no throw.
  private:
    T *ptr_;
};

class ScopedLock : NonCopyable// Scoped Lock idiom
{
  public:
    ScopedLock (Lock & l) : lock_(l) { lock_.acquire(); }
    ~ScopedLock () throw () { lock_.release(); } 
  private:
    Lock& lock_;
};

It is important in this idiom that the destructor should not throw exceptions. Therefore, the destructors have no-throw specification but it is optional.

Many classes that manage resources using RAII, do not have legitimate copy semantics (e.g., network connections, database cursors, mutex). The NonCopyable class shown before prevents copying of objects that implement RAII.
Such classes should not be used in STL containers.
If copy semantics are desired, boost::shared_ptr can be used to manage memory resources.

std::auto_ptr and boost::scoped_ptr are ways of quickly using RAII idiom for memory resources.

Limitations

The limitations are related to destructors: no return value and can't throw exceptions (C++ defines a harsh rule, which says that an exception escaping from a destructor during stack unwinding will cause program termination, see beware of exceptions in destructors).

Scope Guard

Intent

Similar to RAII:

Unlike RAII, Scope Guard will not release resources when there is no error. It is enhanced RAII implementation with a conditional check.


class ScopeGuard
{
public:
  ScopeGuard () 
   : engaged_ (true) 
  { /* Acquire resources here. */ }
  
  ~ScopeGuard ()  
  { 
    if (engaged_) 
     { /* Release resources here. */} 
  }
  void release () 
  { 
     engaged_ = false; 
     /* Resources no longer be released */ 
  }
private:
  bool engaged_;
};

void some_init_function ()
{
  ScopeGuard guard;
  // ...... Something may throw here. If it does we release resources.
  guard.release (); // Resources will not be released in normal execution.
}

Safe bool

WikiBooks. To provide boolean tests for a class but restricting it from taking participation in unwanted expressions.


struct Testable
{
	operator bool() const {
		return false;
	}
};
struct AnotherTestable
{
	operator bool() const {
		return true;
	}
};
int main (void)
{
	Testable a;
	AnotherTestable b;
	if (a == b) { /* blah blah blah*/ }
	if (a < 0) { /* blah blah blah*/ }
	// The above comparisons are accidental and are not intended but the compiler happily compiles them.
	return 0;
}

struct Testable
{
	explicit operator bool() const {
		return false;
	}
};

int main()
{
	Testable a, b;
	if (a)		{ /*do something*/ }  // this is correct
	if (a == b) { /*do something*/ }  // compiler error
}

How does if (fstream) return a value of true or false?

StackOverflow.