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 reference-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.
_M_grab()is called on from elsewhere, and here the extra copy of the allocator is done just to see whether the allocator is both copy-constructible and whether copies compare equal? Obviously, if the first is not true, the call won't even compile, but if the latter is not true, the resource management will still behave properly.