std::string 的引用计数
我正在查看 basic_string
的代码(与 g++ 4.2.1 捆绑在一起)。复制构造函数使用grab()
函数来“抓取”字符串的副本(增加其引用计数):
_CharT* _M_grab( const _Alloc& __alloc1, const _Alloc& __alloc2 ) {
return (!_M_is_leaked() && __alloc1 == __alloc2) ? _M_refcopy() : _M_clone(__alloc1);
}
仅当两个字符串的分配器为一样——有道理。但是,复制构造函数是:
basic_string(const basic_string& __str)
: _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()), __str.get_allocator()),
__str.get_allocator())
{ }
传递给 _M_grab()
的第一个分配器是第二个分配器的副本。为什么? allocator
的 operator==()
可能返回 false 的唯一方法是用户使用自定义分配器。然而,即使这是真的,您也会认为复制的分配器会与原始分配器相等,对吧?那么:
- 为什么要比较分配器呢?
- 为什么要复制构造一个分配器并将副本与原始版本进行比较?
- 将副本与其原始版本进行比较会返回 false 的用例是什么?
更新
是的,_M_grab()
用于另一处:用于赋值。在这种情况下,传递给 _M_grab()
的分配器是不同的。美好的。但似乎仍然没有理由在构造函数中对字符串进行复制构造和比较分配器。
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
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我知道 GCC 团队的推理,但这是我的假设:
用于调试?分配器必须相同。
那么它可以重用_M_grab()吗?
不应该发生吗?
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?
如果从一个分配器分配的对象可以被另一个分配器释放,则分配器比较相等。如果是这种情况,那么两个字符串可以共享对同一分配器的引用;否则,每个分配器都需要自己的分配器。
比较发生在
_M_grab
中,在这种特殊情况下,它不知道一个参数是从另一个参数复制构造的。_M_grab
也从assign
调用,其中两个字符串可能具有不同的分配器。分配器应始终与自身的副本进行比较。
更新
也没有特别好的理由来实现两个几乎相同的
_M_grab()
版本来避免不必要的比较,而这种情况(对于大多数分配器)无论如何都会在编译时发生。也许您认为这样的微观优化是可取的;显然这段代码的作者没有。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
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.