智能指针,c++11,单例,类型转换

news2025/1/18 1:55:05
c++11
unique_ptr
防拷贝

shared_ptr / weak_ptr:

引用计数,支持拷贝

面试

手写shared_ptr

各种ptr的特性对比,  不会问定制删除器和weak_ptr,但是问shared_ptr时,可以往这边延展.

单例

保证一写数据在一个进程中,只有一份,并且方便访问修改.

饿汉模式

在main函数之前就创建了对象

#include <iostream>
#include <vector>
#include <string>
#include <thread>
#include <mutex>
#include <time.h>
using namespace std;

class Singleton
{
public:
	static Singleton* GetInstance()
	{
		return _ins;
	}

	void Add(const string& str)
	{
		_mtx.lock();
		_v.push_back(str);
		_mtx.unlock();
	}

	void Print()
	{
		_mtx.lock();
		for (auto& e : _v)
		{
			cout << e << endl;
		}
		cout << endl;
		_mtx.unlock();
	}
private:
	//限制类外面随意创建对象
	Singleton() 
	{}
private:
	mutex _mtx;
	vector<string> _v;	//想让vector的数据,在全局只有唯一一份
	static Singleton* _ins;
};

Singleton* Singleton::_ins = new Singleton;

int main()
{
	//Singleton s1;
	//static Singleton s2;
	Singleton::GetInstance()->Add("张三" );
	Singleton::GetInstance()->Add("李四");
	Singleton::GetInstance()->Print();

	int n = 10;
	thread t1([n]() {
		for (size_t i = 0; i < n; i++)
		{
			Singleton::GetInstance()->Add("t1线程" + to_string(rand()));	//添加随机数
		}
	});
	thread t2([n]() {
		for (size_t i = 0; i < n; i++)
		{
			Singleton::GetInstance()->Add("t2线程" + to_string(rand()));	//添加随机数
		}
	});

	t1.join();
	t2.join();
	Singleton::GetInstance()->Print();

	return 0;
}

张三
李四

张三
李四
t1线程41
t1线程18467
t1线程6334
t1线程26500
t2线程41
t2线程18467
t2线程6334
t1线程19169
t1线程15724
t1线程11478
t1线程29358
t2线程26500
t2线程19169
t2线程15724
t2线程11478
t1线程26962
t2线程29358
t1线程24464
t2线程26962
t2线程24464

懒汉模式 

第一次访问实例对象时才创建

class Singleton
{
public:
	static Singleton* GetInstance()
	{
		if (_ins == nullptr)		//提高效率
		{
			_imtx.lock();
			if (_ins == nullptr)		//线程安全和只new一次
			{
				_ins = new Singleton;
			}
			_imtx.unlock();
		}
		return _ins;
	}

	void Add(const string& str)
	{
		_vmtx.lock();
		_v.push_back(str);
		_vmtx.unlock();
	}

	void Print()
	{
		_vmtx.lock();
		for (auto& e : _v)
		{
			cout << e << endl;
		}
		cout << endl;
		_vmtx.unlock();
	}
private:
	//限制类外面随意创建对象
	Singleton() 
	{}
private:
	mutex _vmtx;
	vector<string> _v;	//想让vector的数据,在全局只有唯一一份
	static Singleton* _ins;
	static mutex _imtx;
};

Singleton* Singleton::_ins = nullptr;
mutex Singleton::_imtx;

int main()
{
	srand(time(0));

	int n = 10;
	thread t1([n]() {
		for (size_t i = 0; i < n; i++)
		{
			Singleton::GetInstance()->Add("t1线程" + to_string(rand()));	//添加随机数
		}
	});
	thread t2([n]() {
		for (size_t i = 0; i < n; i++)
		{
			Singleton::GetInstance()->Add("t2线程" + to_string(rand()));	//添加随机数
		}
	});

	t1.join();
	t2.join();
	Singleton::GetInstance()->Print();

	return 0;
}
	static Singleton* GetInstance()   //懒汉模式 另一种写法
	{
		//C++11之前,不能保证初始化静态局部对象的线程安全问题(不安全)
		//C++11之后,可以保证初始化静态局部对象的线程安全问题(安全)
		static Singleton inst;
		return &inst;
	}

懒汉和饿汉的优缺点

饿汉:

缺点:

1. 如果单例对象很大,main函数之前就要申请,第一暂时不需要使用却占用资源, 第二程序启动会变慢.

2. 如果两个单例都是饿汉,并相互有依赖关系, 要求单例1先创建, 单例2再创建(例如数据库先启动,缓存后启动), 饿汉无法控制谁先创建的顺序

优点:

比懒汉简单

懒汉优点:解决了饿汉的缺点

懒汉缺点:比饿汉复杂

懒汉有线程安全问题, 饿汉没有线程安全问题

保证单例对象回收
#include <iostream>
#include <vector>
#include <string>
#include <thread>
#include <mutex>
#include <time.h>
using namespace std;

class Singleton
{
public:
	static Singleton* GetInstance()
	{
		if (_ins == nullptr)		//提高效率
		{
			_imtx.lock();
			if (_ins == nullptr)		//线程安全和只new一次
			{
				_ins = new Singleton;
			}
			_imtx.unlock();
		}
		return _ins;
	}

	//不需要显式地释放单例对象
	//因为一般全局都要使用单例对象. 所以不需要显式地释放. 程序结束时最后会系统释放
	//有些特殊场景,想显式的释放一下
	static void DelInstance()
	{
		_imtx.lock();
		if (_ins != nullptr)
		{
			delete _ins;
			_ins = nullptr;
		}
		_imtx.unlock();
	}

	//单例对象回收
	class GC		//内部类.写成外部类也可以
	{
	public:
		~GC()
		{
			DelInstance();
		}
	};

	static GC _gc;	//定义静态全局gc对象
	~Singleton()
	{
		//持久化-永久存下来
		// // 要求程序在结束前, 将数据写到文件中.
		//单例对象析构时做持久化.
	}	

	void Add(const string& str)
	{
		_vmtx.lock();
		_v.push_back(str);
		_vmtx.unlock();
	}

	void Print()
	{
		_vmtx.lock();
		for (auto& e : _v)
		{
			cout << e << endl;
		}
		cout << endl;
		_vmtx.unlock();
	}
private:
	//限制类外面随意创建对象
	Singleton() 
	{}
private:
	mutex _vmtx;
	vector<string> _v;	//想让vector的数据,在全局只有唯一一份
	static Singleton* _ins;
	static mutex _imtx;
};

Singleton* Singleton::_ins = nullptr;
mutex Singleton::_imtx;

Singleton::GC Singleton::_gc;
int main()
{
	srand(time(0));

	int n = 10;
	thread t1([n]() {
		for (size_t i = 0; i < n; i++)
		{
			Singleton::GetInstance()->Add("t1线程" + to_string(rand()));	//添加随机数
		}
	});
	thread t2([n]() {
		for (size_t i = 0; i < n; i++)
		{
			Singleton::GetInstance()->Add("t2线程" + to_string(rand()));	//添加随机数
		}
	});

	t1.join();
	t2.join();
	Singleton::GetInstance()->Print();

	return 0;
}

t1线程41
t2线程41
t1线程18467
t2线程18467
t2线程6334
t2线程26500
t2线程19169
t1线程6334
t1线程26500
t1线程19169
t1线程15724
t1线程11478
t1线程29358
t1线程26962
t1线程24464
t2线程15724
t2线程11478
t2线程29358
t2线程26962
t2线程24464

补充:防拷贝
	//无论饿汉,懒汉,都要防拷贝
	Singleton(const Singleton& s) = delete;	//不封拷贝构造无法保证单例
		//Singleton s(*Singleton::GetInstance());
	Singleton& operator=(const Singleton& s) = delete;

类型转换

static_cast

reinterpret_cast

const_cast

dynamic_cast

前三种为了解决c语言使用不规范 ~,第四种是c++相较于c语言新增的。

class A
{
public:
	virtual void f() {}
};

class B : public A
{

};

void fun(A* pa, const string& s)
{
	std::cout << "pa" << s << std::endl;

	B* pb1 = (B*)pa;
	B* pb2 = dynamic_cast<B*>(pa);	//安全的 

	std::cout << "[强制转换]pb1:" << pb1 << endl;
	std::cout << "[dynamic_cast转换]pb2:" << pb2 << endl << endl;
	//检查父类指针,如果原本指向父类对象,就转失败;
	//如果原本指向子类对象,就转成功
}


int main()
{
	//double d = 12.34;
	//int a = static_cast<int>(d);	//相似类型可以转, 整形不可转成指针  隐式类型转换
	//cout << a << endl;

	//int *p = reinterpret_cast<int*>(a);	//重新解释的转换 ,不可用static_cast 强制类型转换

	//const int a = 2;
	//int* p = const_cast<int*>(&a);	//对应c语言的下一行
	//int* p2 = (int*)&a;
	//*p = 3;
	//cout << a << endl;	//2
	//cout << *p << endl;	//3
	//cout << *p2 << endl;
	//加了const后,编译器优化,把a存到寄存器, 从寄存器取a. 
	//
	
	//4 .dynamic_cast 动态转换  只有c++有
	//指针 / 引用可转 , 对象不可转
	

	A a;
	B b;
	//bb = (B)aa;	//对象不可转
	//dynamic转换是安全的, 强制类型转换是不安全的
	fun(&a, "指向父类对象");
	fun(&b, "指向子类对象");

	return 0;
}

pa指向父类对象
[强制转换]pb1:0000009495EFF498
[dynamic_cast转换]pb2:0000000000000000

pa指向子类对象
[强制转换]pb1:0000009495EFF4B8
[dynamic_cast转换]pb2:0000009495EFF4B8
 

RAII  ---- 资源 请求 is 初始化

RTTI ---- Run-time Type identifification的简称,即:运行时类型识别。

C++ 通过以下方式来支持 RTTI
1. typeid 运算符
	cout << typeid(a).name() << endl;	//class A
2. dynamic_cast 运算符
识别指针是指向父类还是子类?
3. decltype
常见面试题
1. C++ 中的 4 中类型转化分别是: _________ _________ _________ _________
2. 说说 4 中类型转化的应用场景。

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java中的多态究竟是什么?

目录 一.概念二.使用条件三.重写1.概念2.使用条件3.与重载对比4.举例5.为什么需要重写1.重写规则 2.静态绑定--重载3.动态绑定--重写 四.向上转型第一种传参方式&#xff1a;直接赋值第二种传参方式&#xff1a;通过传参优缺点 五.向下转型举例缺点 六.多态的优缺点优点缺点 一…

【Python 千题 —— 基础篇】账号登录

题目描述 题目描述 简易登录系统。你的账号密码分别是 “student”&#xff0c;“123456”&#xff1b;请使用 if-else 设计一个简易登录系统&#xff0c;输入账号密码。登陆成功输出 “Welcome !”&#xff0c;登录失败输出 “Login failed !” 输入描述 输入账号和密码。…

分类预测 | Matlab实现PSO-LSTM粒子群算法优化长短期记忆神经网络的数据多输入分类预测

分类预测 | Matlab实现PSO-LSTM粒子群算法优化长短期记忆神经网络的数据多输入分类预测 目录 分类预测 | Matlab实现PSO-LSTM粒子群算法优化长短期记忆神经网络的数据多输入分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现PSO-LSTM粒子群算法优化长短…

vue3+vite搭建后台项目-1 引入element-plus 中文包,打包时报错问题

vue3vite搭建后台项目-1 引入element-plus 中文包,打包时报错问题 终端报错 If theelement-pluspackage actually exposes this module, try adding a new declaration (.d.ts) file containing are moduleelement-plus/dist/locale/zh-cn.mjsdec import zhCn fromelement-plus…

VS c++多文件编译

前言&#xff1a;记录下我这个菜鸡学习的过程&#xff0c;如有错误恳请指出&#xff0c;不胜感激&#xff01; 1.简单多文件编译调试 文件目录&#xff1a; 编译&#xff1a; -g选项是告诉编译器生成调试信息&#xff0c;这样可以在程序崩溃或出现错误时更容易地进行调试。这…

思维模型 多看效应

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。越熟悉&#xff0c;越喜欢。 1 多看效应的应用 1.1 多看效应在广告和营销领域的应用 1 可口可乐之歌 可口可乐公司在 20 世纪 60 年代推出了“可口可乐之歌”广告&#xff0c;这个广告通…

华为ensp:交换机接口划分vlan

现在要把 e0/0/1 接口放入vlan1 e0/0/2 接口放入vlan2 e0/0/3 接口放入vlan3 默认所有接口都在vlan1所以 e0/0/0 接口不用动 1.创建vlan 进入系统视图模式 直接输入 vlan 编号 即可创建对应vlan vlan 编号 vlan 2 创建vlan2 vlan 3 创建vlan3 2.将接口进入vlan…

【java:牛客每日三十题总结-5】

java:牛客每日三十题总结 总结如下 总结如下 -Xmx&#xff1a;最大堆大小 -Xms&#xff1a;初始堆大小 -Xmn:年轻代大小 -XXSurvivorRatio&#xff1a;年轻代中Eden区与Survivor区的大小比值 年轻代5120m&#xff0c; Eden&#xff1a;Survivor3&#xff0c;Survivor区大小102…

【Git】的分支和标签的讲解及实际应用场景

目录 一、讲解 1. 环境讲述 2. 应用原因 3. 分支标签的区别 二、分支 1. 命令 2. 场景应用 三、标签 1. 命令 2. 标签规范 3. 应用场景 每篇一获 一、讲解 1. 环境讲述 当软件从开发到正式环境部署的过程中&#xff0c;不同环境的作用如下&#xff1a; 开发环境&a…

电脑清灰涂硅脂后电脑CPU温度不降反升

目录 一.问题描述二.问题解决三.拆机注意事项四.影响散热的主要因素说明1.通风差2.硅脂材料差3.硅脂涂抹方式错误 一.问题描述 电脑型号&#xff1a;暗影精灵5 测温工具&#xff1a;硬件狗狗&#xff08;只要是测温软件都可以&#xff0c;比如omen hub和Core Temp…&#xff0…

LeetCode146.LRU缓存

写了一个小时&#xff0c;终于把示例跑过了&#xff0c;没想到啊提交之后第19/22个测试用例没过 我把测试用例的输出复制在word上看看和我的有什么不同&#xff0c;没想到有18页的word&#xff0c;然后我一直检查终于找出了问题&#xff0c;而且这个bug真的太活该了&#xff0c…

Sprint Boot 学习路线 4

微服务 Spring Microservices是一个框架&#xff0c;它使用Spring框架更容易地构建和管理基于微服务的应用程序。微服务是一种架构风格&#xff0c;其中一个大型应用程序被构建为一组小型、独立可部署的服务。每个服务具有明确定义的职责&#xff0c;并通过API与其他服务通信。…

CCNA课程实验-13-PPPoE

目录 实验条件网络拓朴需求 配置实现基础配置模拟运营商ISP配置ISP的DNS配置出口路由器OR基础配置PC1基础配置 出口路由器OR配置PPPOE拨号创建NAT(PAT端口复用) PC1测试结果 实验条件 网络拓朴 需求 OR使用PPPoE的方式向ISP发送拨号的用户名和密码&#xff0c;用户名&#xf…

前端面试题之vue篇

vue基础 vue的基本原理 当一个Vue实例创建时&#xff0c;Vue会遍历data中的属性&#xff0c;用Object.defineProperty(Vue使用proxy)转换为getter/setter&#xff0c;并且在内部追踪相关依赖&#xff0c;在属性被访问和修改时通知变化。每个组件实例都有相应的watcher程序实例…

蓝桥杯每日一题2023.11.11

题目描述 “蓝桥杯”练习系统 (lanqiao.cn) 题目分析 对于此题首先想到的是暴力分析&#xff0c;使用前缀和&#xff0c;这样方便算出每一区间的大小&#xff0c;枚举长度和其实位置&#xff0c;循环计算出所有区间的和进行判断&#xff0c;输出答案。 非满分暴力写法&#…

电脑出现病毒提示解决办法

已检测:Trojan:Win32/WacatacA!ml 状态:已隔离 隔离的文件在不会损害设备的受限区域内。系统将自动删除它们 日期:2023/11/1013:21详细信息这个程序很危险&#xff0c;而且执行来自攻击者的命令 受影响的项目: driver: haStdnetfilter file: C:WINDOWSsystem32\drivers\haStdne…

企业计算机中了mkp勒索病毒怎么办,服务器中了勒索病毒如何处理

计算机技术的不断发展给企业的生产生活提供了极大便利&#xff0c;但也为企业带来了网络安全威胁。近期&#xff0c;云天数据恢复中心陆续接到很多企业的求助&#xff0c;企业的计算机服务器遭到了mkp勒索病毒攻击&#xff0c;导致企业的所有工作无法正常开展&#xff0c;给企业…

upload 文件自动上传写法,前后端 下载流文件流

<el-uploadv-model:file-list"fileList":action"app.api/student/student/import":headers"{// Content-Type: multipart/form-data;boundary----split-boundary, 此处切记不要加&#xff0c;否则会造成后端报错 Required request part file is…

【Java 进阶篇】Java 中 JQuery 对象和 JS 对象:区别与转换

在前端开发中&#xff0c;经常会涉及到 JavaScript&#xff08;JS&#xff09;和 jQuery 的使用。这两者都是前端开发中非常重要的工具&#xff0c;但它们之间存在一些区别。本文将详细介绍 Java 中的 JQuery 对象和 JS 对象的区别&#xff0c;并讨论它们之间的转换方法。 1. …

多状态Dp问题——买卖股票的最佳时机含冷冻期

目录 一&#xff0c;题目 二&#xff0c;题目接口 三&#xff0c;解题思路及其代码 一&#xff0c;题目 给定一个整数数组prices&#xff0c;其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成…