V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
lhx2008
V2EX  ›  问与答

C++的 STL 普通容器为什么不做 Copy on write 的特性呢?

  •  
  •   lhx2008 · 2019-04-23 19:03:59 +08:00 · 2047 次点击
    这是一个创建于 2046 天前的主题,其中的信息可能已经有所发展或是发生改变。
    初学 C++,理解不对请指教。

    COW,像 string 是有做的,但是 vector 这些就没有。

    但是调用 vector 的拷贝构造函数(值传递,对象成员初始化)可能会经常发生,但是大部分情况下不一定会改副本。

    如果每次都复制内存,会不会效率会很低呢?如果让开发者带指针传递,又增加了开发者的负担
    20 条回复    2019-04-24 15:18:37 +08:00
    0x11901
        1
    0x11901  
       2019-04-23 19:05:45 +08:00
    引用了解下。
    lhx2008
        2
    lhx2008  
    OP
       2019-04-23 19:06:53 +08:00
    @0x11901 给一个对象的成员变量赋值,如何使用引用呢?
    lhx2008
        3
    lhx2008  
    OP
       2019-04-23 19:13:23 +08:00   ❤️ 1
    @0x11901 准确来说是,引用传递进来只是少一次复制,但是如果用于成员变量初始化的情况,还是得复制的
    0x11901
        4
    0x11901  
       2019-04-23 19:13:47 +08:00   ❤️ 1
    @lhx2008 那这个问题和 cpp 关系不大吧……如果是基本类型,直接值传递,如果非基本数据,一般就是传引用就够了。
    lhx2008
        5
    lhx2008  
    OP
       2019-04-23 19:14:46 +08:00
    @0x11901 还有就是返回值(临时对象)的时候,也可能会发生复制
    0x11901
        6
    0x11901  
       2019-04-23 19:15:20 +08:00
    @lhx2008 你的意思是不同对象共享同一个非基本数据的引用?一处修改,每个对象的成员变量都会修改?
    lhx2008
        7
    lhx2008  
    OP
       2019-04-23 19:16:15 +08:00
    @0x11901 COW 的意思就是修改时再复制,这样不修改就不用复制
    0x11901
        8
    0x11901  
       2019-04-23 19:16:38 +08:00
    @lhx2008 返回的时候如果不想触发拷贝构造,这个是你的事。
    0x11901
        9
    0x11901  
       2019-04-23 19:19:02 +08:00   ❤️ 1
    @lhx2008 那应该就是标准委员会的老人们觉得没必要,各种特性争了这么多年了都没有进 c++标准,但是你可以自己实现。
    lhx2008
        10
    lhx2008  
    OP
       2019-04-23 19:20:22 +08:00
    @0x11901 触不触发拷贝构造,应该是看编译器优不优化吧?还是我理解有误
    exonuclease
        11
    exonuclease  
       2019-04-23 19:21:15 +08:00 via iPhone   ❤️ 1
    因为你可以重载索引操作符和拷贝构造函数自己折腾一个啊
    0x11901
        12
    0x11901  
       2019-04-23 19:24:22 +08:00   ❤️ 1
    @lhx2008 如果你没有用 c++17 标准的"copy elision",完全很有可能在返回时触发拷贝构造,编译器不会优化你明确指出想要拷贝构造的地方。
    secondwtq
        13
    secondwtq  
       2019-04-23 19:41:39 +08:00   ❤️ 2
    C++11 已经不允许 COW string 了。

    这种问题得从 C++ 特色去考虑:COW 在修改时会 invalidate 掉 iterator 和 reference
    msg7086
        14
    msg7086  
       2019-04-23 22:01:09 +08:00
    因为 C 和 C++设计上就是允许你进行非常底层的操作的?
    是否 Copy 完全要看调用者的需求,而不是自动处理吧。
    lhx2008
        15
    lhx2008  
    OP
       2019-04-23 22:13:37 +08:00
    @msg7086 事实就是这么残酷,有些时候栈上分配的部分必须 Copy。
    一个方法是再用一个(智能)指针指向堆上内存,然后 Copy 的只是只用 Copy 指针,开销小一点。
    如果用 COW 的话,栈上也是要复制的(很少),只是堆上部分复不复制看情况。
    blinue
        16
    blinue  
       2019-04-23 22:22:22 +08:00 via Android   ❤️ 1
    c++11 引入的移动构造和赋值事实上足以解决很多问题,更何况 cow 的引入会使迭代器的复杂度倍增,原罪在于指针!
    lynskylate
        17
    lynskylate  
       2019-04-24 02:02:01 +08:00 via Android
    string 的 cow 已经被认为是失败的设计了
    iceheart
        18
    iceheart  
       2019-04-24 07:03:17 +08:00 via Android
    既然你有这需求了,为啥不自己实现一个这样的容器?
    做好了再拿出来去打标准委员会的脸。
    shihira
        19
    shihira  
       2019-04-24 09:19:38 +08:00 via Android
    如果在业务中有这样的需求,或者拷贝成为了性能瓶颈,你可以自己写一个这样的 vector 也不费什么劲,但这不适合作为标准库。标准库就是要逻辑清晰、行为有可预见性,过早优化是万恶之源
    Skypemifan
        20
    Skypemifan  
       2019-04-24 15:18:37 +08:00
    COW 是指写时拷贝复制吗??
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2951 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 15:01 · PVG 23:01 · LAX 07:01 · JFK 10:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.