
on Wed Dec 03 2008, Ion GaztaƱaga <igaztanaga-AT-gmail.com> wrote:
Mathias Gaunard wrote:
The overhead I'm talking about is that allowing an empty state in the object might have a cost.
A simple example is that if you have a function release(resource&), that releases a valid resource, and you want to wrap that resource using RAII, you have to write the destructor as
if(!is_empty) release(res);
instead of simply
release(res);
So you need to maintain a boolean (size overhead) and perform a branching (runtime overhead).
Usually, however, at least the size overhead can be eliminated since there is a special resource value reserved for the null resource.
You are right. My point is that if you want to support a movable object:
{ non_copyable_file_descriptor fd("filename"); non_copyable_file_descriptor fd2(move(fd)); //Both destroyed here //fd2 closes the file descriptor //fd is "empty" }
you need to encode the "empty" state. Making the default constructor public or not is not the point. If we want to support non-destructible move-semantics we will always have this overhead in destructors.
It is true that we need an empty state for move semantics. However, the appearance of said state can naturally be restricted to situations where the object is about to be either destroyed or assigned, which means that it's reasonable to say that the object's other operations are only available when the state isn't empty. It's somewhat less-reasonable to say that other operations are unavailable for empty objects when the empty state is available via a constructor (although the built-ins do it). I know it's a little wishy-washy, but I think limiting construction to producing fully-capable objects can still be valuable even in the face of an empty state introduced for move semantics.
There is a proposal to optimize these destructors:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2754.html
N2754: "Additional concepts: TriviallyDestructibleAfterMove and TriviallyReallocatable"
This will be very useful in containers, but I'm just thinking if compilers could be smart enough to avoid calling destructors for moved objects if the are TriviallyDestructibleAfterMove:
{ //non_copyable_file_descriptor is //"TriviallyDestructibleAfterMove": non_copyable_file_descriptor fd("filename"); non_copyable_file_descriptor fd2(move(fd)); //Both destroyed here //fd2 closes the file descriptor //The compiler bypasses fd's destructor }
That would be kewl. -- Dave Abrahams BoostPro Computing http://www.boostpro.com