简体   繁体   English

迭代器和引用计数字符串

[英]Iterators and reference counted strings

If we consider a std::string implementation that uses reference counting, consider this scenario: 如果我们考虑使用引用计数的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;
}

What happens in L1 and L2? L1和L2会发生什么? Is the reference counting broken and a deep copy is performed? 引用计数是否已损坏并执行了深层复制? I think so, but my concern says that if that occurs, doing a simple: 我是这么认为的,但我担心的是,如果发生这种情况,做一个简单的事情:

cout << german[1] << endl; 

or a simple: 还是简单的:

cout << *(german.begin()) << endl;

in non-const contexts would perform unnecessary deep copies. 在非const上下文中将执行不必要的深层复制。 Am I right? 我对吗? How do the implementations deal with this detail? 这些实现如何处理这个细节?

You are correct, a copy would be made in all four examples (L1, L2, and the two below), even though for the latter two it's unnecessary. 你是对的,在所有四个例子(L1,L2和下面两个)中都会有一个副本,即使对于后两个例子也没有必要。

Unfortunately when the non-const version of operator[] is called or a non-const iterator is dereferenced, there is no way for the implementation to tell whether or not the resulting non-const reference will be used to modify the object, so it has to play it safe and make a copy. 不幸的是,当调用operator []的非const版本或取消引用非const迭代器时,实现无法判断生成的非const引用是否将用于修改对象,因此它必须安全地播放并制作副本。

C++11 added functions cbegin() and cend() to strings and other containers which return const iterators even if called on a non-const object. C ++ 11增加的功能cbegin()cend()到串并返回即使称为非const对象上const的迭代器的其它容器。 This helps alleviate the problem. 这有助于缓解这个问题。 I'm not aware of a comparable solution for operator[]. 我不知道运营商[]的可比解决方案。

Note: having operator[] or the iterator's operator*() return a proxy type, as some of the other answerers suggested, is not really an option because it breaks container requirements, one of which is that these functions return actual references. 注意:让operator []或迭代器的运算符*()返回一个代理类型,正如其他一些回答者建议的那样,实际上不是一个选项,因为它打破了容器需求,其中之一就是这些函数返回实际的引用。 (This is why everyone now agrees that vector<bool> is a mistake - it uses proxies in this way). (这就是为什么现在每个人都同意vector<bool>是一个错误 - 它以这种方式使用代理)。

(Of course, if you're writing your own reference-counted class, there's nothing stopping you from using proxy types to achieve this.) (当然,如果您正在编写自己的引用计数类,那么没有什么可以阻止您使用代理类型来实现此目的。)

One way to achieve this is through proxy classes. 实现此目的的一种方法是通过代理类。 So when you index into a string instead if getting a char you get an object that looks and feels like a char. 所以当你索引到一个字符串而不是获得一个字符时,你会得到一个外观和感觉像char的对象。 When a write is performed on it it causes deep copy on the original string. 当对其执行写入时,它会导致原始字符串的深层复制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM