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

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.rhkb.cn/news/188440.html

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

相关文章

竞赛 车道线检测(自动驾驶 机器视觉)

0 前言 无人驾驶技术是机器学习为主的一门前沿领域&#xff0c;在无人驾驶领域中机器学习的各种算法随处可见&#xff0c;今天学长给大家介绍无人驾驶技术中的车道线检测。 1 车道线检测 在无人驾驶领域每一个任务都是相当复杂&#xff0c;看上去无从下手。那么面对这样极其…

win10网络和Internet设置

win10网络设置 win10进入网络设置的常用入口有两个 第一个入口 桌面右下角右键网络图标&#xff0c;然后打开“网络和Internt设置” 第二个入口 桌面的“我的网络”快捷方式&#xff0c;或者我的电脑进去后&#xff0c;左侧栏找到“网络” 右键“属性” 可以看到&#xff0c;…

图论10-哈密尔顿回路和哈密尔顿路径+状态压缩+记忆化搜索

文章目录 1 哈密尔顿回路2 哈密尔顿回路算法实现2.1 常规回溯算法2.2 引入变量记录剩余未访问的节点数量 3 哈密尔顿路径问题4 状态压缩4.1 查看第i位是否为14.2 设置第i位是为1或者04.3 小结4.4 状态压缩在哈密尔顿问题中的应用 5 记忆化搜索5.1 记忆化搜索与递推区别5.2 记忆…

基于单片机的空调智能控制器的设计

**单片机设计介绍&#xff0c;基于单片机的空调智能控制器的设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的空调智能控制器需要具备输入输出端口、定时器、计数器等模块&#xff0c;以便对空调进行精确控制。下…

补坑:Java的字符串String类(3):再谈String

不太熟悉字符串的可以看看这两篇文章 补坑&#xff1a;Java的字符串String类&#xff08;1&#xff09;-CSDN博客 补坑&#xff1a;Java的字符串String类&#xff08;2&#xff09;&#xff1a;一些OJ题目-CSDN博客 字符串创建对象 public static void main(String[] args) …

ES6学习

let和const命名 let基本用法-块级作用域 在es6中可以使用let声明变量&#xff0c;用法类似于var ⚠️ let声明的变量&#xff0c;只在let命令所在的代码块内有效 {let a 10;var b 20; } console.log(a); //a is not defined console.log(b); //20不存在变量提升 var命令…

【11】使用透视投影建立一个3D空间的测试

核心操作&#xff1a; 1.proj view model 这三个矩阵 glm::mat4 mvp m_Proj * m_View * model; m_Shader->Bind(); m_Shader->SetUniformMat4f("u_MVP", mvp);着色器里面就&#xff1a; proj:投影矩阵&#xff0c;可以选择正交投影&#xff0c;或者透视投影…

javaSE学习笔记(二)数组,类,对象,成员变量,匿名对象,构造方法,static,final,封装,继承,多态

目录 三、面向对象 1.概述 面向过程与面向对象 面向对象编程特点 面向对象三个基本特征 2.数组 数组定义格式 数组的初始化 动态初始化 静态初始化 数组的内存分配 Java中的内存分配 数组的内存分配 数组的角标 数组的基本操作 二维数组&#xff08;实际开发几乎…

【网络编程】网络层——IP协议

文章目录 基本概念路径选择主机和路由器 IP协议格式分片与组装网段划分IP地址的数量限制私网IP地址和公网IP地址深入认识局域网路由 基本概念 TCP作为传输层控制协议&#xff0c;其保证的是数据传输的可靠性和传输效率&#xff0c;但TCP提供的仅仅是数据传输的策略&#xff0c…

通过商品ID获取到京东商品详情页面数据,京东商品详情官方开放平台API接口,京东APP详情接口,可以拿到sku价格,销售价演示案例

淘宝SKU详情接口是指&#xff0c;获取指定商品的SKU的详细信息。SKU是指提供不同的商品参数组合的一个机制&#xff0c;通过不同的SKU来标识商品的不同组合形式&#xff0c;如颜色、尺寸等。SKU详情接口可以帮助开发者获取指定商品的SKU列表&#xff0c;以及每个SKU的属性、库存…

多目标优化框架

随着模型越来越复杂&#xff0c;优化目标越来越多&#xff0c;传统算法都慢慢地无法胜任复杂优化任务&#xff0c;更为智能的优化方法也就应运而生了。其中有一类是进化优化算法&#xff0c;这类算法的思想来源是自然界的“优胜劣汰”法则&#xff0c;通过不停地保留好的个体最…

ubuntu16.04 交叉编译 mbedtls

在为客户交叉编译项目时需要依赖 mbedtls&#xff0c; 客户的机器是 arm64 的 ubuntu 16.04&#xff0c; 交叉编译过程中遇到几个问题。 首先&#xff0c; mbedtls 需要依赖 python, 在 cmake 的过程中&#xff0c; 如果不是使用系统默认的 cmake 可能会导致&#xff0c;mbedt…

Matlab的多项式留数与极点的计算

Matlab的多项式留数与极点的计算 以下面的多项式为例&#xff1a; 运算代码&#xff1a; clc clear closesyms p % 定义多项式 Zp(5*p^571*p^370*p)/(2*p^635*p^4117*p^236); % 提取分子与分母 [I,D]numden(Zp); Idouble(coeffs(I,p,"All"));%分子 Ddouble(coeffs…

【数据结构】单链表OJ题(一)

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 前言一、移除链表元素二、寻找链表中间结点三、输出链表倒数第k个结点四、反转单链表五…

STM32MPU6050角度的读取(STM32驱动MPU6050)

注&#xff1a;文末附STM32驱动MPU6050代码工程链接&#xff0c;需要的读者请自取。 一、MPU6050介绍 MPU6050是一款集成了三轴陀螺仪和三轴加速度计的传感器芯片&#xff0c;由英国飞利浦半导体&#xff08;现为恩智浦半导体&#xff09;公司生产。它通过电子接口&#xff08…

conda环境中pytorch1.2.0版本安装包安装一直失败解决办法!!!

conda环境中pytorch1.2.0版本安装包安装一直失败解决办法 cuda10.0以及cudnn7.4现在以及安装完成&#xff0c;就差torch的安装了&#xff0c;现在torch我要装的是1.2.0版本的&#xff0c;安装包以及下载好了&#xff0c;安装包都是在这个网站里下载的&#xff08;点此进入&…

Postgres的级数生成函数generate_series应用

Postgres的级数生成函数generate_series应用 引用&#xff1a;http://postgres.cn/docs/12/functions-srf.html 函数文档 函数 参数类型 返回类型 描述 generate_series(start, stop) int、bigint或者numeric setof int、setof bigint或者setof numeric&#xff08;与参数类型相…

【React入门实战】实现Todo代办

文章目录 效果功能-状态管理相关接口定义相关方法定义 UIinput输入框&#xff1a;回车添加todo标题列表列表项Main 总体代码 非常简单入门的react-todo练习&#xff0c;代码写的很小白。 效果 技术栈&#xff1a;react-typeScript 数据分为代办Todo和已办完Done&#xff0c;可…

php实现钉钉机器人推送消息和图片内容(完整版)

先来看下实现效果: 代码如下: function send_dingtalk_markdown($webhook , $title , $message "", $atMobiles [], $atUserIds []) {$data ["msgtype" > "markdown","markdown" > ["title" > $title,&quo…

一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?

目录 1解题思路&#xff1a; 2代码如下&#xff1a; 3运行结果&#xff1a; 4总结&#xff1a; 5介绍&#xff1a; 1解题思路&#xff1a; 利用循环&#xff08;穷举法&#xff09;来 对 所 需要的数 进行确定 2代码如下&#xff1a; #include <stdio.h>int main() …