C++引用计数

文章目录

  • 1. 什么是引用计数
  • 2. 引用计数的实现
  • 3. 示例代码

1. 什么是引用计数

引用计数(reference count)的核心思想是使用一个计数器来标识当前指针指向的对象被多少类的对象所使用(即记录指针指向对象被引用的次数)。它允许有多个相同值的对象共享这个值的实现。引用计数的使用常有两个目的:

  • 简化跟踪堆中(也即C++中new出来的)的对象的过程。一旦一个对象通过调用new被分配出来,记录谁拥有这个对象是很重要的,因为其所有者要负责对它进行delete。但是对象所有者可以有多个,且所有权能够被传递,这就使得内存跟踪变得困难。引用计数可以跟踪对象所有权,并能够自动销毁对象。可以说引用计数是个简单的垃圾回收体系。

  • 节省内存,提高程序运行效率。如果很多对象有相同的值,为这多个相同的值存储多个副本是很浪费空间的,所以最好做法是让左右对象都共享同一个值的实现。C++标准库中string类采取一种称为”写时复制“的技术,使得只有当字符串被修改的时候才创建各自的拷贝,否则可能(标准库允许使用但没强制要求)采用引用计数技术来管理共享对象的多个对象。

2. 引用计数的实现

使用引用计数实现智能指针的关键是,引用计数应该存在哪里。引用计数应该是某个类对象和其复制对象共享的, 而指针成员恰好有这样的特性, 故可以在类中多声明一个size_t* 的成员,用来表示引用计数。

  • 构造函数中创建类的新对象时,初始化引用计数为1;
  • 拷贝构造函数复制指针,并使相应的引用计数增加1;
  • 赋值操作减少左操作数所指对象的引用计数,增加右操作数所指对象的引用计数;
  • 析构函数使引用计数减少1,并且当引用计数为1时,释放指针所指向的对象;

在这里插入图片描述

3. 示例代码

#include <iostream>
#include <string>using std::string; using std::ostream; using std::cout; using std::size_t;class HasPtr {friend ostream& print(ostream&, const HasPtr&);
public:// string():构造空的string类对象,既空字符串HasPtr(const string& s = string()) : ps(new string(s)), i(0), use(new size_t(1)) { } // constructor~HasPtr(); // 析构函数HasPtr(const HasPtr& rhs) : ps(rhs.ps), i(rhs.i), use(rhs.use) { ++* use; } // 拷贝构造函数HasPtr& operator=(const HasPtr&); // 运算符重载
private:string* ps; // ps是一个指针,指向string类型int i;size_t* use; // use是一个指针,指向size_t类型
};// 析构函数的定义
HasPtr::~HasPtr()
{if (-- * use == 0) {	// 如果引用计数为变0delete ps;			// 释放string内存delete use;			// 释放计数器内存}
}// 运算符重载的定义
HasPtr&
HasPtr::operator=(const HasPtr& rhs)
{++* rhs.use;			// 递增右侧运算对象的引用计数if (-- * use == 0) {	// 然后递减本对象的引用计数delete ps;			// 如果没有其他用户delete use;			// 释放本对象分配的成员}ps = rhs.ps;			// 将数据从rhs拷贝到本对象i = rhs.i;use = rhs.use;return *this;			// 返回本对象
}// 友元函数的定义
ostream& print(ostream& os, const HasPtr& p)
{os << p.ps << ' ' << *p.ps << ' ' << *p.use;return os;
}void func(const HasPtr& p)
{HasPtr temp;temp = p;cout << "p: ";print(cout, p) << '\n';;cout << "temp: ";print(cout, temp) << '\n';;
}int main()
{cout << "HasPtr str1(\"copy me\"), str2;\n";HasPtr str1("copy me"), str2;cout << "str1: ";print(cout, str1) << '\n';cout << "str2: ";print(cout, str2) << '\n';cout << "\nstr2 = str1;\n";str2 = str1;cout << "str1: ";print(cout, str1) << '\n';cout << "str2: ";print(cout, str2) << '\n';cout << "\nfunc(str1);\n";func(str1);cout << "\nstr1: ";print(cout, str1) << '\n';cout << "str2: ";print(cout, str2) << '\n';return 0;}

输出结果:

HasPtr str1("copy me"), str2;
str1: 0116D990 copy me 1
str2: 011654E8  1str2 = str1;
str1: 0116D990 copy me 2
str2: 0116D990 copy me 2func(str1);
p: 0116D990 copy me 3
temp: 0116D990 copy me 3str1: 0116D990 copy me 2
str2: 0116D990 copy me 2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/4588.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL数据库——主从复制

目录 前言一、读写分离概述1. 什么是读写分离&#xff1f;2. 为什么要读写分离呢&#xff1f;3. 什么时候要读写分离&#xff1f;4. 主从复制与读写分离5. mysq支持的复制类型6. 主从复制的工作过程7. MySQL主从复制延迟 二、主从复制配置方法主服务器配置从服务器配置 前言 在…

MySQL的Join

1.Join用法 Join连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接。 内连接又叫等值连接,此时的inner可以省略。 USING语句 MySQL中连接SQL语句中,ON子句的语法格式为:table1.column_name = table2.column_name。当模式设计对联接表的列采用了相同的命名样…

基于matlab使用校准相机拍摄的两张图像中恢复相机运动并重建场景的3D结构(附源码)

一、前言 运动结构 &#xff08;SfM&#xff09; 是从一组 3-D 图像估计场景的 2-D 结构的过程。此示例演示如何从两个图像估计校准相机的姿势&#xff0c;将场景的三维结构重建为未知比例因子&#xff0c;然后通过检测已知大小的对象来恢复实际比例因子。 此示例演示如何从使…

低代码平台在ERP软件中的作用

很多人认为 低代码开发平台的出现颠覆了传统的软件开发模式&#xff0c;对软件开发行业造成冲击&#xff0c;其实低代码开发平台的出现只是提高了软件开发的效率&#xff0c;并不是要颠覆软件开发的模式。低代码平台在erp软件开发中的作用还是比较明显的。下面一起来了解一下相…

《kafka 核心技术与实战》课程学习笔记(九)

客户端都有哪些不常见但是很高级的功能&#xff1f; 什么是 Kafka 拦截器&#xff1f; 拦截器基本思想就是允许应用程序在不修改逻辑的情况下&#xff0c;动态地实现一组可插拔的事件处理逻辑链。它能够在主业务操作的前后多个时间点上插入对应的“拦截”逻辑。Spring MVC 拦…

安科瑞故障电弧探测器在建筑电气的设计与应用

安科瑞 崔丽洁 【摘要】&#xff1a;电气设备是建筑中不可缺少的一部分&#xff0c;具有较为重要的作用和意义&#xff0c;在应用过程中不仅能够提升建筑本身实用性能&#xff0c;而且可为消费者提供更加优良的生活环境。但设备一旦在运行过程中出现故障&#xff0c;不仅会影响…

Flutter卡片分享功能实现:将你的内容分享给世界

前言 在app中&#xff0c;在实现分享功能的时候&#xff0c;通常会有一种以卡片形式展示和分享内容的分享方式。这种功能可以将信息以整洁、易读的方式呈现给用户&#xff0c;使他们能够快速了解内容的关键信息&#xff0c;并将其分享给其他人。那么在这篇文章中&#xff0c;就…

python: more Layer Architecture and its Implementation in Python

sql server: --学生表 DROP TABLE DuStudentList GO create table DuStudentList (StudentId INT IDENTITY(1,1) PRIMARY KEY,StudentName nvarchar(50),StudentNO varchar(50), --学号StudentBirthday datetime --学生生日 ) go mod…

UE4 Cesium离线生成地形

地理空间数据云 首先进这个网址&#xff0c;下载对应的tif以及高程&#xff08;DEM&#xff09; 下载CesiumLab2 在地形切片中点击添加&#xff0c;将黑白图像数据&#xff0c;添加&#xff0c;选择存储类型为散列文件&#xff0c;选择输出路径 再选择影像切片&#xff0c;选择…

Sublime Text 初步使用

Sublime Text &#xff0c;最初被设计为一个具有丰富扩展功能的Vim。 Sublime Text具有漂亮的用户界面和强大的功能&#xff0c;例如代码缩略图&#xff0c;Python的插件&#xff0c;代码段等。还可自定义键绑定&#xff0c;菜单和工具栏。Sublime Text 的主要功能包括&#xf…

PyTorch开放神经网络交换(Open Neural Network Exchange)ONNX通用格式模型的熟悉

我们在深度学习中可以发现有很多不同格式的模型文件&#xff0c;比如不同的框架就有各自的文件格式&#xff1a;.model、.h5、.pb、.pkl、.pt、.pth等等&#xff0c;各自有标准就带来互通的不便&#xff0c;所以微软、Meta和亚马逊在内的合作伙伴社区一起搞一个ONNX(Open Neura…

jupyter notebook优化

一&#xff0e;这个是jupyter notebook主题设置的相关教程&#xff0c;如果经常看着高亮的屏幕&#xff0c;对于眼睛会是一种损伤&#xff01; https://blog.csdn.net/qq_41566627/article/details/104984796?utm_mediumdistribute.pc_relevant.none-task-blog-2%7Edefault%7…