4

我正在查看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==()for可能返回 false的唯一方法allocator是用户使用自定义分配器。但是,即使这是真的,您也会认为复制的分配器将与其原始分配器进行比较,对吗?所以:

  1. 为什么要比较分配器?
  2. 为什么要复制构建分配器并将副本与原始文件进行比较?
  3. 将副本与其原件进行比较会返回 false 的用例是什么?

更新

是的,_M_grab()用在另一个地方:分配。在这种情况下,传递给的分配器_M_grab() 不同的。美好的。但是似乎仍然没有理由同时复制构造然后比较构造函数中的分配器string

4

2 回答 2

1

我知道 zip 关于 GCC 团队的推理,但这是我的假设:

  1. 用于调试?分配器必须相同。

  2. 所以它可以重用_M_grab()?

  3. 永远不应该发生?

于 2010-07-28T16:14:30.313 回答
1
  1. 如果从一个分配器分配的对象可以与另一个分配器一起释放,则分配器比较相等。如果是这样,那么两个字符串可以共享对同一个分配器的引用;否则,每个人都需要自己的分配器。

  2. 比较发生在 内_M_grab,在这种特殊情况下,它不知道一个参数是从另一个参数复制构造的。_M_grab也被调用 from assign,其中两个字符串可能有不同的分配器。

  3. 分配器应始终与自身的副本进行比较。

更新

但是似乎仍然没有理由同时复制构造然后比较构造函数中的分配器以获取字符串。

也没有特别好的理由实现两个几乎相同的版本_M_grab()来避免不必要的比较,这(对于大多数分配器)无论如何都会在编译时发生。也许你认为这样的微优化是可取的;显然这段代码的作者没有。

于 2010-07-28T16:27:20.350 回答