• COW写时复制


    1、Scott Meyers
    、推荐我们,在真正需要一个存储空间时才去声明变量(分配内存),这样会得到程序在运行时最小的内存花销
    2、执行到那才会去做分配内存这种比较耗时的工作,这会给我们的程序在运行时有比较好的性能写时才拷贝(Copy-On- Write)技术,是编程界“懒惰行为”——拖延战术的产物
    #include <iostream>
    #include<string>
    #include<stdio.h>
    using namespace std;
    int main()
    {
            string str1="hello world";
            string str2=str1;
            string str3=str2;
            printf("str1 = %p ",str1.c_str());
            printf("str2 = %p ",str2.c_str());
            printf("str3 = %p ",str3.c_str());
            str1[1]='X';
            cout<<"after Copy-on-Write"<<endl;
            printf("str1 = %p ",str1.c_str());
            printf("str2 = %p ",str2.c_str());
            printf("str3 = %p ",str3.c_str());
            return 0;
    }


    ● string类中有一个私有成员,其实是一个char*,记录从堆上分配内存的地址,其在构造时分配内存,在析构时释放内存
    ● 因为是从堆上分配内存,所以string类在维护这块内存上是格外小心的
    ● string类在返回这块内存地址时,只返回const char*,也就是只读的
    ● const char* c_str() const;
    ● 如果要写,则只能通过string提供的方法进行数据的改写。


    Copy-On-Write的原理是什么?
    ● Copy-On-Write一定使用了“引用计数”,必然有一个变量类似于RefCnt
    ● 当第一个string对象str1构造时,string的构造函数会根据传入的参数从堆上分配内存
    ● 当有其它string对象复制str1时,这个RefCnt会自动加1
    ● 当有对象析构时,这个计数会减1;直到最后一个对象析构时,RefCnt为0,此时,程序才会真正的Free这块从堆上分配的内存
    string类在什么情况下才共享内存的?
    1)以一个对象构造自己(复制构造函数)
    只需要在string类的拷贝构造函数中做点处理,让其引用计数累加
    2)以一个对象赋值(重载赋值运算符)
    string类在什么情况下触发写时才拷贝?
    ● 在共享同一块内存的类发生内容改变时,才会发生Copy-On-Write
    ● 比如string类的 []、=、+=、+、操作符赋值,还有一些string类中诸如insert、replace、append等成员函数
    Copy-On-Write时,发生了什么?
    if  ( --RefCnt>0 ) {        
        char* tmp =  (char*) malloc(strlen(_Ptr)+1);        
        strcpy(tmp, _Ptr);        
        _Ptr = tmp;
    }
    引用计数RefCnt 大于1,表示这个内存是被共享的。
    Copy-On-Write的具体实现是怎么样的?
    string h1 = "hello";
    string h2= h1;
    string h3;
    h3 = h2;
    string w1 = "world";
    string w2("");
    w2=w1;
    h1、h2、h3共享同一块内存, w1、w2共享同一块内存
    Copy-On-Write的具体实现是怎么样的?
    ● String类创建的对象的内存是在堆上动态分配的,既然共享内存的各个对象指向的是同一个内存区,那我们就在这块共享内存上多分配一点空间来存放这个引用计数RefCnt
    ● 这样一来,所有共享一块内存区的对象都有同样的一个引用计数
    解决方案:
    当为string对象分配内存时,我们要多分配一个空间用来存放这个引用计数的值,只要发生拷贝构造或赋值时,这个内存的值就会加1。而在内容修改时,string类为查看这个引用计数是否大于1,如果refcnt大于1,表示有人在共享这块内存,那么自己需要先做一份拷贝,然后把引用计数减去1,再把数据拷贝过来



  • 相关阅读:
    【CodeForces 788B】奇妙的一笔画问题
    数论day2——离散对数、元根
    学习阶段总结(1)
    Flask特殊装饰器
    Flask蓝图
    Flask对象配置
    Flask实例化配置
    Flask路由
    Flask Session
    Flask jinja2
  • 原文地址:https://www.cnblogs.com/meihao1203/p/8949370.html
Copyright © 2020-2023  润新知