C++引用计数

这篇具有很好参考价值的文章主要介绍了C++引用计数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 什么是引用计数

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

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

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

2. 引用计数的实现

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

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

C++引用计数

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) {	// 如果引用计数为变0
		delete 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;

}

输出结果:文章来源地址https://www.toymoban.com/news/detail-515295.html

HasPtr str1("copy me"), str2;
str1: 0116D990 copy me 1
str2: 011654E8  1

str2 = str1;
str1: 0116D990 copy me 2
str2: 0116D990 copy me 2

func(str1);
p: 0116D990 copy me 3
temp: 0116D990 copy me 3

str1: 0116D990 copy me 2
str2: 0116D990 copy me 2

到了这里,关于C++引用计数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Mysql count 带条件计数

    mysql 统计条数很简单, 使用 count 函数就行,但是带条件统计,可能有些小伙伴跟我一样,还有些疑问,废话不多说 上代码 表中三条数据 区别:count(*) 包含 null 值的条目,count(字段) 则不包含 例如: select count(*) from sys_user // 返回 3 条数据 select count(name) from sys_user // 返回 2数据

    2024年02月11日
    浏览(28)
  • 计数排序 (Counting Sort)_20230709

    前言 计数排序的对象一般为分布在[0-k]范围内的非负整数,计数器类似哈希函数的线性映射,它确定了数值本身和它在序列中的总数量之间的基本关系。它的本质是计算某个数在临时序列中(原序列大小相同,但下标从1开始)的位置,在后续的映射中,直接把某个位置上放置

    2024年02月13日
    浏览(38)
  • JVM7:垃圾回收是什么?从运行时数据区看垃圾回收到底回收哪块区域?垃圾回收如何去回收?垃圾回收策略,引用计数算法及循环引用问题,可达性分析算法

    在Java中,垃圾回收(Garbage Collection,简称GC),是自动管理内存的机制。它负责检测不再使用的对象,并释放它们所占用的内存,以供其他对象使用。 JVM内存模型认识的差不多了,就应该思考,什么样的内存模型适合什么样的GC策略,包括垃圾回收为什么会出现。实际上,很多

    2024年02月11日
    浏览(36)
  • POJ - 2282 The Counting Problem(数位DP 计数问题)

    Given two integers a and b, we write the numbers between a and b, inclusive, in a list. Your task is to calculate the number of occurrences of each digit. For example, if a = 1024 a = 1024 a = 1024 and b = 1032 b = 1032 b = 1032 , the list will be 1024 1024 1024 1025 1025 1025 1026 1026 1026 1027 1027 1027 1028 1028 1028 1029 1029 1029 1030 1030 1030 1031 10

    2023年04月17日
    浏览(38)
  • C++入门:引用是什么

    目录 1.引用的概念 2.引用的特征 3.常引用 4.引用使用场景 5.传值,传引用效率比较 6.引用与指针的区别 引用 不是新定义一个变量,而是 给已存在变量取了一个别名 ,编译器不会为引用变量开辟内存空 间,它和它引用的变量 共用同一块内存空间 。 语法: 类型 引用变量名

    2024年02月11日
    浏览(41)
  • C++ vector元素类型为什么不能是引用

    vectorT 引用必须要进行初始化,不能初始化为空对象,初始化后不能改变指向 引用是别名,不是对象,没有实际地址, 不能定义引用的指针 ,也 不能定义引用的引用 推荐一个零声学院项目课,个人觉得老师讲得不错,分享给大家: 零声白金学习卡(含基础架构/高性能存储

    2024年02月15日
    浏览(59)
  • 近4w字吐血整理!只要你认真看完【C++编程核心知识】分分钟吊打面试官(包含:内存、函数、引用、类与对象、文件操作)

    🌈个人主页:godspeed_lucip 🔥 系列专栏:C++从基础到进阶 🏆🏆关注博主,随时获取更多关于C++的优质内容!🏆🏆 🍉配套markdown文件下载:请翻阅至文章底部获取 本阶段主要针对C++ 面向对象 编程技术做详细讲解,探讨C++中的核心和精髓。 C++程序在执行时,将内存大方向划

    2024年01月17日
    浏览(47)
  • python引用from的变量报错Unresolved reference ‘xxxx‘

    我这里是一个文件中集中定义了常量,然后使用from xxxx import xxxx引入 然后发现执行报错: 而且在class中只有这一个def中的xxxx.常量会报错。并且其他def中引用都正常,手打时,pycharm提示也正常。 原因是我在def中for循环中写的是 这里与from重复了导致的报错 如果不是,那就检

    2024年02月10日
    浏览(35)
  • RCU安全引用计数

    原文网址:https://lwn.net/Articles/93617 原文作者:Corbet 原文时间:2004年7月14日 内核提供了一种用于实现引用计数的简单机制kref;该机制是今年3月份完成的。kref机制的核心思想是,提供支持原子操作的计数器,用于对未决引用【outstanding references】进行计数。如果计数器数值为

    2024年02月11日
    浏览(42)
  • iOS——引用计数(一)

    自动引用计数(ARC,Automatic Reference Counting)是指内存管理中对引用采取自动计数的技术。 满足以下要求后,我们的代码就无需再次键入retain或者是release代码了: 使用Xcode 4.2或以上版本 使用LLVM编译器3.0或以上版本 编译器选项中设置ARC为有效 在以上条件下编译源代码时,编

    2024年02月07日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包