I came across this code in Feb 2013 issue of "Overload" Magazine. I understand the code provided, but completly I do miss it's purpose, neither the analogy with std:: auto_ptr and sparing alloc/ dealloc cycles. If someone could re-explain this "recipe" in his own words. The description is as this :
Recipe #2 – Containers with ‘move’ semantics Recipe #2 is admittedly a rather weird one, but every good cookbook should contain at least one weird recipe, so here goes. In high-performance code, there are scenarios, where you need to have a container which stores complex objects (such objects including allocated storage etc.), but those objects are only moved around and are never copied. Providing a copy constructor for such objects can be either difficult (for example, if such an object includes a file handle) or undesirable for performance reasons (if such an object contains allocated memory, copying which would be expensive). One common way to deal with this is to use some kind of reference-counted pointer (or something similar to auto_ptr<>); this is a viable option, but it has the associated cost of extra allocation/ deallocation, and in really high-performance code, this might be an issue. In such cases, an approach similar to the following could help (rephrasing a proverb, you could say that weird times require weird measures) – see Listing 2.
//class X is our complicated class
class StackOfX {
// stack is just one example; any other type of
// container (including maps, sets, lists, etc.)
// can be written in a similar manner
struct ShadowX { char data[ sizeof(X) ]; };
typedef vector<ShadowX> ShadowV;
ShadowV v;
void push( /* move-in */ X& x ) {
ShadowX& sx = (ShadowX&)x;
v.insert( v.end(), sx );
}
const X& operator[]( int i ) const {
return (const X&)v[ i ];
}
void pop( /* move-out */ X& x ) {
ShadowV::iterator it = v.end() - 1;
ShadowX& sx = (ShadowX&)x;
sx = *it;
v.erase( it );
}
~StackOfX() {
for( ShadowV::iterator it = v.begin();
it != v.end(); ++it ) {
X& x = (X&)(*it);
x.X::~X();
}
}
};