在c++中关于对自定义对象的构造和析构有一种不同的看法,那就是引用计数
它在面临某些情况时,要优于直接对对象构造析构。
引用计数是什么以及它的的作用
在c++中我们定义一个类,假如用这个类建立对象需要在堆中开辟内存时,必然要对这个类编写构造和析构函数来开辟和释放对象内存。在拷贝构造和赋值重载的场景下,我们需要进行深拷贝,才能真正实现同一个类的新对象的初始化。每次都要深拷贝,那么就有人提出了新的想法,那就是引用计数。
引用计数它是记录指向同一块内存的对象数,当构造时就对这个数字加加,析构时对这个数字减减,当这
款内存只有一 个对象维护时也就是这个数字为1时(这个数字是由自己决定)才会释放块内存
当有多个对象使用这款内存时,才会对这个对象进行深拷贝,重新使用新的内存来存储相同数据,
同时修改数据,也叫写时拷贝。
它相当于把对象的构造给延迟了,但他修改时还是要做深拷贝这个工作,那么如果在使用这个对象的过程中,不需要修改它,那么就不用做深拷贝这个动作,提高了效率。
我们可以在两个平台上看看不同编译器的结果:
Linux上:
我们编写这样的代码运行的到下面的结果:
可以看到两个对象的地址是一样的。这就说明了引用计数的存在,现在我们修改一下s1:
可以看到完成了深拷贝。
在VS2022上:
#include <iostream>
using namespace std;
#include <string>
int main()
{
string s0("hhhhhhhhhh");
string s1(s0);
cout << (void*)s0.c_str() << endl;
cout << (void*)s1.c_str() << endl;
s1.push_back('s');
cout << (void*)s0.c_str() << endl;
cout << (void*)s1.c_str() << endl;
return 0;
}
可以看到不同的编译器显示结果是不同的。
基于我的能力实现引用计数,我会在对象开辟内存时总是开辟多一点内存来存储这个数,访问的时候用适应大小的指针访问修改即可。
引用计数的好处
引用计数可以跟踪对象所有权,并能够自动销毁对象。 节省内存,提高程序运行效率。