stl容器是否使用隐式共享?

时间:2013-02-05 20:11:17

标签: c++ stl

众所周知,Qt小部件使用implicit sharing。所以我感兴趣的是stl容器std::vectorstd::string也使用隐式共享。

如果不是,为什么?因为它非常有用。

如果答案是肯定的,我们如何确定?我需要简单的C ++ stl程序,它表明stl容器使用隐式共享。复制时不执行深层复制。

4 个答案:

答案 0 :(得分:10)

没有。他们不能。当您尝试修改容器的内容,或者甚至在其上调用可变begin()时,它将意味着潜在的写入时复制,从而使容器的所有引用和迭代器无效。这将是一个难以调试的情况,并且是禁止的。

虽然std::string在技术上不是容器,但是自C ++ 11以来仍然禁止进行写时复制:

  

引用basic_string序列元素的引用,指针和迭代器可能会被该basic_string对象的以下用法无效:
  ...
   - 调用非const成员函数,除运算符[],at,front,back,begin,rbegin,end和rend。

[string.require]

  

...因为它非常有用。

嘿,为什么?通过引用传递几乎总能解决所有性能问题'。原子引用计数在多处理器机器上本质上是不可扩展的。

答案 1 :(得分:4)

除了其他人对容器中CoW行为的反对意见外,还有一些其他内容。这些都属于违反惯例的行为类别,因此会引起毫无戒心的开发人员的奇怪错误。

<强>例外

允许CoW意味着容器上的无害变异操作可能会失败,除非他们不这样做。对operator[]std::vector

std::string {{1}}造成特别危害

线程

有人可能会合理地期望能够复制构造容器,其明确目的是将其交给另一个线程,而不必担心以后的并发性。 CoW不是这样。

答案 2 :(得分:2)

正如similar question中所注意到的那样:

  

C ++标准不禁止或强制要求写入或其他任何内容   std::string的其他实施细节。只要是语义   并且实现可以选择满足复杂性要求   无论它喜欢什么样的实施策略。

我认为,std::vector

也是如此

另外,您可能对此主题感兴趣:How is std::string implemented

答案 3 :(得分:1)

STL容器不使用隐式共享。它们始终具有纯价值语义。

原因是运行时性能:在多线程程序(可能但不一定在多核主机上运行)中,管家数据的锁定开销(例如引用计数,写入前复制时锁定)远远超过了纯值副本的开销,完全没有特殊的线程含义。预计在大型std::maps周围遭受复制的程序将实现显式共享,以避免复制。

实际上,在STL std::string的早期, did 使用隐式共享。但是,当第一个多核CPU出现时,它就被丢弃了。