美文网首页
写时拷贝

写时拷贝

作者: Otis4631 | 来源:发表于2018-03-07 20:06 被阅读0次

什么是写时拷贝

写时拷贝(copy-on-write, COW)就是等到修改数据时才真正分配内存空间,这是对程序性能的优化,可以延迟甚至是避免内存拷贝,当然目的就是避免不必要的内存拷贝。

其实我们对写时拷贝并不陌生,Linux fork和STL string是比较典型的写时拷贝应用,本文只讨论STL string的写时拷贝。

string类的实现必然有个char*成员变量,用以存放string的内容,写时拷贝针对的对象就是这个char*成员变量。通过赋值或拷贝构造类操作,不管派生多少份string“副本”,每个“副本”的char*成员都是指向相同的地址,也就是共享同一块内存,直到某个“副本”执行string写操作时,才会触发写时拷贝,拷贝一份新的内存空间出来,然后在新空间上执行写操作。显然,那些只读的“副本”节省了内存分配的时间和空间。

听起来有点懵,对于没了解过写时拷贝的同学,会感觉完全颠覆平常对string的认知,下面我们来看一下实际例子。

写时拷贝例子

图片描述

如上代码所示,调用拷贝构造函数生成str2,调用赋值操作符生成str3,那么str2与str3是否有分配内存空间来存储内容“abc”呢?

图片描述

运行结果告诉我们,str1、str2与str3是共享内存空间的(char*成员指向相同的地址)。那么问题来了,对str1、str2或str3内容的修改是否会互相影响呢?答案是,只要遵守STL的约定来修改,是会触发写时拷贝的,不会互相影响(毕竟平时一直这样用也没有问题)。

图片描述 图片描述

可以看到,对str1重新复制,修改str3的值,都会触发写时拷贝,分配了新的空间。由于str1、str3都分配了新的空间,str2就可以继续使用原来的空间了。

写时拷贝原理

看了上面的例子,相信大家都已明白写时拷贝的表象了。但我们不能满足于现象,还要知道实现原理。应该很多同学都能猜到,string肯定是使用计数器来记录引用数,当有新的string对象共享内存块时,计数器+1,当有对象触发写时拷贝或析构时,计数器-1。

那么计数器存放在哪里呢?这是对象级别的计数器,由若干个对象共享,string类成员变量、静态变量或全局变量都不能满足要求。最合适的就是在堆里分配空间专门存储这个计数器,由第一个创建的对象分配并初始化计数器,其他对象按照约定引用计数器。我们知道string的内存空间就在堆上,那么直接在这块区上多分配一个空间来存储计数器是最方便的,所有共享这块内存的string对象都能访问计数器。事实上STL就是这么实现的,在string内存空间的最前面分配了空间存储计数器,如下图所示(图片摘自引文):

图片描述

string的所有赋值、拷贝构造操作,计数器都会+1;修改string数据时,先判断计数器是否为0(0代表没有其他对象共享内存空间),为0则可以直接使用内存空间(如例子中的str2),否则触发写时拷贝,计数器-1,拷贝一份数据出来修改,并且新的内存计数器置0;string对象析构时,如果计数器为0则释放内存空间,否则计数器也要-1。

相关文章

  • 写时拷贝

    什么是写时拷贝 写时拷贝(copy-on-write, COW)就是等到修改数据时才真正分配内存空间,这是对程序性...

  • linux写时拷贝

    转载于Copy-On-Write COW 技术简介_Kuzury-CSDN博客[https://blog.csdn...

  • Python42_多任务之进程

    进程 ps:创建子进程时,会将父进程的代码拷贝一份,但是这个拷贝是“写时拷贝”,即,只有当子进程对数据进程修改时才...

  • swift 协议的写时拷贝

    其实这只是协议中的一个小的知识点,但是个人觉得这是对协议的一种优化,可以拿来学习一下。 swift的协议概念: O...

  • 深拷贝、浅拷贝

    父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。 深拷贝同浅拷贝的区别:浅拷贝...

  • 面试题整理

    父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。 深拷贝同浅拷贝的区别:浅拷贝...

  • iOS面试基础一

    #父类实现深拷贝时,子类如何实现深度拷贝.父类没有实现深拷贝时,子类如何实现深度拷贝.# <(1)深拷贝同浅拷贝的...

  • 0. iOS面试题基础篇

    1. 父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。 1.1 深拷贝同浅拷贝...

  • iOS基础知识点01

    1. 父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。 1.1 深拷贝同浅拷贝...

  • iOS知识点(一)

    1.1 父类实现深拷贝时,子类如何实现深度拷贝。 父类没有实现深拷贝时,子类如何实现深度拷贝。深拷贝同浅拷贝的区别...

网友评论

      本文标题:写时拷贝

      本文链接:https://www.haomeiwen.com/subject/ihhzwxtx.html