我正在查看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()
的第一个分配器是第二个分配器的副本。为什么? operator==()
allocator
可能返回false的唯一方法是用户是否使用自定义分配器。但是,即使这是真的,你也会认为复制的分配器与原来的分配器相当,对吧?所以:
是的,_M_grab()
用于另一个地方:用于分配。在这种情况下,传递给_M_grab()
的分配器与不同。精细。但似乎没有理由在{em>构造函数中复制构造然后比较string
中的分配器。
答案 0 :(得分:1)
我知道关于海湾合作委员会小组的推理的拉链,但这是我的假设:
进行调试?分配器必须是相同的。
所以它可以重用_M_grab()?
永远不应该发生?
答案 1 :(得分:1)
如果从一个分配的对象可以与另一个分开,则分配器比较相等。如果是这种情况,则两个字符串可以共享对同一分配器的引用;否则,每个人都需要自己的分配器。
比较发生在_M_grab
内,它不知道在这种特殊情况下,一个参数是从另一个参数复制构造的。 _M_grab
也是从assign
调用的,其中两个字符串可能有不同的分配器。
分配器应始终与其自身的副本进行比较。
<强>更新强>
但似乎没有理由复制构造,然后在构造函数中比较分配器的字符串。
没有特别好的理由来实现两个几乎完全相同的_M_grab()
版本以避免不必要的比较,这对于大多数分配器来说无论如何都会在编译时发生。也许你认为这样的微优化是可取的;显然这段代码的作者没有。