Essential Tools Module User's Guide : Chapter 11 Scope Guard Classes : RWTRefHolder<T>
RWTRefHolder<T>
RWTRefHolder<T> is a reference wrapper object that allows you to pass a reference to, rather than a copy of, an object. Its use allows you to see changes made to the values held within the scope guard object after the guard was constructed.
RWTRefHolder<T> provides a single make function to create an instance of the class:
 
rwtMakeRef(T& t)
Why Use RWTRefHolder<T>
All parameters passed to the rwtMakeScopeGuard() family of functions are held by value within the scope guard. These values are later passed as parameters to the named function when the guard destructor is invoked. Note that since the parameters are held by value, changes to values of objects that have been copied into the scope guard will not be visible when the guard function is invoked. Example:
 
// ...
void print_string(const RWCString& s) {
printf ("%s\n", s.data());
}
 
// ...
RWCString s;
 
s = "hello world!";
RWScopeGuard sg = rwtMakeScopeGuard(print_string, s);
s = "goodbye!";
// ...
The above code generates the following output:
 
hello world!
The initial value is displayed because the scope guard holds a copy of the RWCString 's' as it was at the time the scope guard was created. If you want the scope guard to see updates to a parameter that is passed after the construction of the guard, you must pass a pointer to that object, or use RWTRefHolder<T> to hold a reference by value.
Example:
 
// ...
RWCString s;
 
s = "hello world!";
RWScopeGuard sg = rwtMakeScopeGuard(print_string, rwtMakeRef(s));
s = "goodbye!";
// ...
 
This code generates the following output:
 
goodbye!
A Note on Pointer and Reference Parameters
It is your responsibility to ensure that any parameters that are bound to the scope guard continue to exist at least as long as the scope guard itself. If a parameter bound to the scope guard is destroyed and the scope guard is not dismissed before the end of the local scope, the behavior of the program is undefined. Example:
 
// ...
void deref_print_string(const RWCString* pstr) {
printf ("%s\n", pstr->data());
}
 
// ...
RWCString* pstr = new RWCString("hello world!");
 
RWScopeGuard sg = rwtMakeScopeGuard(deref_print_string, pstr); //1
 
delete pstr; //2
pstr = 0;
 
sg.dismiss(); //3
//1 Binds the scope guard to pstr.
//2 Deallocates pstr. Now the scope guard holds a pointer to an object that no longer exists. If we allow the guard to go out of scope now, it is equivalent to calling
deref_print_string(pstr);
But the pointer pstr now points to a deallocated object. At this point, the only safe solution is to dismiss the guard in order to prevent the call from occurring on exit from the local scope.
//3 Dismisses the guard.
Note that this is not a problem for values, but is important to be aware of when passing a pointer or reference to the rwtMakeScopeGuard() function.