众所周知,Qt小部件使用implicit sharing。所以我感兴趣的是stl容器std::vector
,std::string
也使用隐式共享。
如果不是,为什么?因为它非常有用。
如果答案是肯定的,我们如何确定?我需要简单的C ++ stl程序,它表明stl容器使用隐式共享。复制时不执行深层复制。
答案 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出现时,它就被丢弃了。