4

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:

  1. Why compare allocators at all?
  2. Why copy-construct an allocator and compare the copy to the original?
  3. 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.

2
  • 1
    I'm not able to see the rest of the code here, but is it possible the real utility is for when _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. Commented Jul 28, 2010 at 16:12
  • @seh: Your "latter" case makes some sense, but I can't think of a use-case where a copy-contructed allocator would not compare equal to its original -- seems like a very bizarre case. However, it's presumably not that uncommon because the authors of this string class considered it. So I'm curious as to what such a case might be. Commented Jul 28, 2010 at 16:22

2 Answers 2

1

I know zip about the reasoning of the GCC team but here are my suppositions:

  1. For debugging? The allocators MUST be the same.

  2. So it can reuse _M_grab()?

  3. Should never happen?

Sign up to request clarification or add additional context in comments.

Comments

1
  1. 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.

  2. 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 from assign, where the two strings may have different allocators.

  3. 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.

3 Comments

If #3 is always true, then why bother to copy construct it? Why not simply pass __str.get_allocator() for both arguments to _M_grab() ?
@Paul: You're right; it looks like the explicit copy is unnecessary, but harmless. get_allocator() returns a copy anyway.
My issue was more with the apparently unnecessary copy construction that with the comparison (which you addressed in your response to my comment); hence your later "Update" seems somewhat of a non sequitur.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.