
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. 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 } Regards, Ion