Reference-counting of std::string
I'm looking at the code for basic_string
(that is bundled with g++ 4.2.1). The copy constructor makes use of a grab()
function to "grab" a copy of a string (increment its r开发者_高级运维eference-count):
_CharT* _M_grab( const _Alloc& __alloc1, const _Alloc& __alloc2 ) {
return (!_M_is_leaked() && __alloc1 == __alloc2) ? _M_refcopy() : _M_clone(__alloc1);
}
This increments the reference-count only if the allocators for the two strings are the same -- makes sense. However, the copy constructor is:
basic_string(const basic_string& __str)
: _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()), __str.get_allocator()),
__str.get_allocator())
{ }
The first allocator that's passed to _M_grab()
is a copy of the second. Why? The only way that operator==()
for allocator
might return false is if the user is using a custom allocator. However, even if that's true, you'd think that a copied allocator would compare equal to its original, right? So:
- Why compare allocators at all?
- Why copy-construct an allocator and compare the copy to the original?
- What's a use-case where comparing a copy with its original would return false?
Update
Yes, _M_grab()
is used in one other place: for assignment. In this case, the allocators passed to _M_grab()
are different. Fine. But there still seems to be no reason to both copy-construct and then compare allocators in the constructor for string
.
I know zip about the reasoning of the GCC team but here are my suppositions:
For debugging? The allocators MUST be the same.
So it can reuse _M_grab()?
Should never happen?
Allocators compare equal if objects allocated from one can be freed with the other. If that's the case, then two strings can share a reference to the same allocator; otherwise, each needs its own allocator.
The comparison happens within
_M_grab
, which doesn't know that one argument has been copy-constructed from the other argument in this particular case._M_grab
is also called fromassign
, where the two strings may have different allocators.An allocator should always compare equal to a copy of itself.
Update
But there still seems to be no reason to both copy-construct and then compare allocators in the constructor for string.
Neither is there a particularly good reason to implement two almost-identical versions of _M_grab()
to avoid the unnecessary comparison, which (for most allocators) will happen at compile time anyway. Maybe you think such a micro-optimisation would be desirable; apparently the author of this code didn't.
精彩评论