Qt 隐式共享
2017-03-22 22:00
274 查看
隐式共享又称为回写机制,当两个对象共享同一份数据,如果数据不改变,则不进行数据的复制。而当某个对象需要改变数据时,则执行深拷贝。
深拷贝:生成对象的一个完整的复制品。
浅拷贝:是一个引用复制(如 仅复制指向共享数据的指针)
隐式共享可以降低对内存和CPU资源的使用,提高程序的运行效率。它使得在函数中(如参数、返回值)使用值传递更有效率。
例:
其中,
(1)QString str2 = str1; 把字符串对象str1赋值给str2(由QString的复制构造函数完成str2的初始化),此时,str2 = “data”。在对str2赋值的时候偶,将发生一次浅拷贝,导致两个QString对象都指向了同一个数据结构。
(2)str2[3] = ‘e’; 对str2的修改,将会导致一次深拷贝,使得str2对象指向一个新的、不同于str1所指的数据结构。此时str1 = “data”, str2 = “date”
(3)str2[0] = ‘f’; 进一步对str2进行修改,但这个操作不会引起任何形式的复制,因为str2指向的数据结构没有被共享。此时,str1 = “data”, str2 = “fate”
(4)str1 = str2:; 将str2赋值给str1。此时,str1 之前指向的数据结构将会从内存中释放掉,str1和str2都指向数据结构“fate”。
在这个例子中使用了[]运算子,list1和list2中的数据结构经过了复制,所以并不是共享的。因此最后显示的两个记忆体位置并不相同,但是使用了at()时的情况是一样的:
所以,在只读的情况下,使用at()方法要比使用[]运算子效率高,因为省去了数据结构的复制成本。
隐式共享之所以称为copy on write,也就是说只要容器中的数据结构内容发生了变化就不再共享,而要复制。就上一个例子而言,如果对list2做了修改,比如:
list2 << "linux";
那么:
cout << &(list1.at(0)) << endl;
此时list1和list2显示的记忆体位置就是不同的。
再比如:
然后,就可以利用这个函数实现数据共享,又不会数据结构复制:
在上面这个代码片段中,function()中的list位置和接收function中的list的retval位置是相同的。
总的来说,QT中所有的容器类都支持隐式共享;此外,QByteArray,QBrush,QPen,QPalette,QBitmap,QImage,QPixmap,QCursor,QDir,QFont和QVariant等也都只是隐式共享机制。
而无论是Java风格还是STL风格的迭代器,使用只读迭代器时,背后也都使用到了隐式共享机制,以增加读取的效率。
深拷贝:生成对象的一个完整的复制品。
浅拷贝:是一个引用复制(如 仅复制指向共享数据的指针)
隐式共享可以降低对内存和CPU资源的使用,提高程序的运行效率。它使得在函数中(如参数、返回值)使用值传递更有效率。
例:
QString str1 = "data"; QString str2 = str1; str2[3] = 'e'; str2[0] = 'f'; str1 = str2;
其中,
(1)QString str2 = str1; 把字符串对象str1赋值给str2(由QString的复制构造函数完成str2的初始化),此时,str2 = “data”。在对str2赋值的时候偶,将发生一次浅拷贝,导致两个QString对象都指向了同一个数据结构。
(2)str2[3] = ‘e’; 对str2的修改,将会导致一次深拷贝,使得str2对象指向一个新的、不同于str1所指的数据结构。此时str1 = “data”, str2 = “date”
(3)str2[0] = ‘f’; 进一步对str2进行修改,但这个操作不会引起任何形式的复制,因为str2指向的数据结构没有被共享。此时,str1 = “data”, str2 = “fate”
(4)str1 = str2:; 将str2赋值给str1。此时,str1 之前指向的数据结构将会从内存中释放掉,str1和str2都指向数据结构“fate”。
———-
其实,在使用Qt容器类的时候会可能用到隐式共享机制(implicit sharing),也叫做copy on write。顾名思义,就是说,在内容有变动的情况下才对容器中的数据结构做复制,否则仅做共享。比如:QList<QString> list1; list1 << "helianthus"; QList<QString> list2 = list1; cout << &list1[0] << endl;
在这个例子中使用了[]运算子,list1和list2中的数据结构经过了复制,所以并不是共享的。因此最后显示的两个记忆体位置并不相同,但是使用了at()时的情况是一样的:
QList<QString> list1; list1 << "x"; QList<QString> list2 = list1; /*QList::at(int i) const:Returns the item at index position i in the list. i must be a valid index position in the list (i.e., 0 <= i < size())*/ cout << &(list1.at(0)) << endl; cout << &(list2.at(0)) < < endl;
所以,在只读的情况下,使用at()方法要比使用[]运算子效率高,因为省去了数据结构的复制成本。
隐式共享之所以称为copy on write,也就是说只要容器中的数据结构内容发生了变化就不再共享,而要复制。就上一个例子而言,如果对list2做了修改,比如:
list2 << "linux";
那么:
cout << &(list1.at(0)) << endl;
此时list1和list2显示的记忆体位置就是不同的。
再比如:
QList<int> function() { QList<int> list; // ...blah..blah cout << &list << endl; return list; }
然后,就可以利用这个函数实现数据共享,又不会数据结构复制:
QList<int> retval= function(); cout << &retval << endl;
在上面这个代码片段中,function()中的list位置和接收function中的list的retval位置是相同的。
总的来说,QT中所有的容器类都支持隐式共享;此外,QByteArray,QBrush,QPen,QPalette,QBitmap,QImage,QPixmap,QCursor,QDir,QFont和QVariant等也都只是隐式共享机制。
而无论是Java风格还是STL风格的迭代器,使用只读迭代器时,背后也都使用到了隐式共享机制,以增加读取的效率。
相关文章推荐
- QT的隐式共享(Implicit Sharing)
- Qt学习:再次理解隐式共享
- Qt之美(三)隐式数据共享
- Qt隐式共享理解
- Qt之美(三)隐式数据共享
- QT 隐式共享 Implicit Sharing
- Qt学习之路(36): Qt容器类之遍历器和隐式数据共享
- C++中的深拷贝和浅拷贝 QT中的深拷贝,浅拷贝和隐式共享
- Qt Implicit Sharing (隐式共享)
- 可恶的QT隐式共享
- Qt学习之路(36): Qt容器类之遍历器和隐式数据共享
- Qt学习05——隐式共享
- Qt框架浅析之一 ------- 隐式共享(Implicit Sharing)
- Qt学习之路(36): Qt容器类之遍历器和隐式数据共享
- Qt学习之路(36): Qt容器类之遍历器和隐式数据共享
- Qt学习:理解隐式共享
- (二十五)Qt : 隐式数据共享(copy on write)
- Qt学习之路(36): Qt容器类之遍历器和隐式数据共享
- Qt——数据的隐式共享
- 隐式共享:qt