迭代器和引用计数字符串

eba*_*onp 7 c++ stl copy-on-write

如果我们考虑使用引用计数的std :: string实现,请考虑以下情况:

int main()
{
  string english = "Hello";
  string german  = english; //refcnt = 2
  string german2 = german;

  /* L1 */ german[1] = 'a';
  /* L2 */ *(german2.begin() + 1) = 'A';

  cout << english << endl << german << endl << german2 << endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

L1和L2会发生什么?引用计数是否已损坏并执行了深层复制?我是这么认为的,但我担心的是,如果发生这种情况,做一个简单的事情:

cout << german[1] << endl; 
Run Code Online (Sandbox Code Playgroud)

还是简单的:

cout << *(german.begin()) << endl;
Run Code Online (Sandbox Code Playgroud)

在非const上下文中将执行不必要的深层复制.我对吗?这些实现如何处理这个细节?

HC4*_*ica 6

你是对的,在所有四个例子(L1,L2和下面两个)中都会有一个副本,即使对于后两个例子也没有必要.

不幸的是,当调用operator []的非const版本或取消引用非const迭代器时,实现无法判断生成的非const引用是否将用于修改对象,因此它必须安全地播放并制作副本.

C++ 11添加了函数cbegin()以及cend()字符串和其他容器,即使在非const对象上调用它们也会返回const迭代器.这有助于缓解这个问题.我不知道运营商[]的可比解决方案.

注:具有操作[]或迭代器的operator*()返回代理类型,因为一些其他的应答者认为,因为它打破了容器的要求,其中之一是,这些函数返回实际参考值是不是一个真正的选择.(这就是为什么现在每个人都同意这vector<bool>是一个错误 - 它以这种方式使用代理).

(当然,如果您正在编写自己的引用计数类,那么没有什么能阻止您使用代理类型来实现此目的.)