首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >迭代器和引用计数字符串

迭代器和引用计数字符串
EN

Stack Overflow用户
提问于 2012-06-22 07:39:09
回答 2查看 236关注 0票数 7

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

代码语言:javascript
复制
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;
}

在L1和L2中发生了什么?是否中断了引用计数并执行了深度复制?我想是的,但我担心的是,如果发生这种情况,做一个简单的:

代码语言:javascript
复制
cout << german[1] << endl; 

或者是一个简单的:

代码语言:javascript
复制
cout << *(german.begin()) << endl;

在非常数上下文中将执行不必要的深度复制。我说的对吗?实现是如何处理这个细节的?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-22 07:59:23

您是对的,在所有四个示例(L1、L2和下面的两个)中都会创建一个副本,尽管对于后两个示例是不必要的。

不幸的是,当非常量版本的operator[]被调用或者非常量迭代器被取消引用时,实现没有办法知道产生的非常量引用是否将用于修改对象,因此它必须确保它的安全并进行复制。

C++11将函数cbegin()cend()添加到字符串和其他容器中,这些容器返回常量迭代器,即使在非常量对象上调用也是如此。这有助于缓解问题。我不知道operator[]有什么类似的解决方案。

注意:让operator[]或迭代器的运算符*()返回代理类型,正如其他一些回答者所建议的那样,并不是一个真正的选择,因为它违反了容器要求,其中之一是这些函数返回实际的引用。(这就是为什么现在每个人都认为vector<bool>是一个错误-它以这种方式使用代理)。

(当然,如果您正在编写自己的引用计数类,那么没有什么可以阻止您使用代理类型来实现这一点。)

票数 6
EN

Stack Overflow用户

发布于 2012-06-22 07:59:20

实现这一点的一种方法是通过代理类。因此,当您索引到一个字符串时,如果获取一个char,您将得到一个看起来和感觉上都像char的对象。当对它执行写操作时,它会导致对原始字符串进行深度复制。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11148355

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档