面试可能会问六:智能指针

2023-05-16

先看一下百度百科的解释:

指针指针

当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝;另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享。

智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数器跟踪该类有多少个对象的指针指向同一对象。

实现原理:

每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,析构函数减少引用计数(如果引用计数减至0,则删除基础对象)。

个人建议:好好读读百度百科这个版本,解释挺好的。此处不再赘述。

个人提供一个简单版的智能指针实现。

运算符重载的角度来看一下。

#pragma once

#include<iostream>
using namespace std;

class Person
{
public :
	Person(int age);
	void showAge();
	~Person();

private :
	int mAge;
};
#include "Person.h"


Person::Person(int age)
{
	this->mAge = age;
}

void Person::showAge()
{
	cout << "年龄为:" << this->mAge << endl;
}

Person::~Person()
{
	cout << "析构函数被调用。" << endl;
}
#include "Person.h"


void test01()
{
	Person p1(10);  //建立在栈中,函数结束由编译器自动销毁。

}


int main()
{
	test01();

	return EXIT_SUCCESS;
}

如果我们把对象建立在栈上,函数在运行结束后,编译器自动回收。

如果我们把对象建立在堆中。new一个指针变量出来。(所有new出来的对象,都返回该类型的指针。)开辟在堆中,就需要我们自己手动去释放。

void test01()
{
	//Person p1(10);  //建立在栈中,函数结束由编译器自动销毁。
	Person *p1 = new Person(10);   // new返回指针类型的对象。
	delete p1;  // 必须手动释放。
}

如果我们的代码有几百行,那么我们很容易遗漏这样的释放。所以在C++11中,有了一个新的特性:指针指针。

用来:用来托管自定义类型的对象,让对象自动的释放。

如何实现呢,我们自己实现一个:写一个智能指针类,就只是管理一个属性:也就是这个自定义类型的指针。Person*。

为了管理这个指针,在构造时,就需要将这个指针传输到构造函数中去,然后整个类,维护这个指针。

class SmartPointer
{
public:
	SmartPointer(Person* person)
	{
		this->person = person;
	}
	~SmartPointer()
	{
		if (this->person != NULL)
		{
			delete this->person;
			this->person = NULL;
		}
	}
private:
	Person* person;
};

如何实现呢?

void test02()
{
	SmartPointer sp(new Person(10));
}

如此即实现了指针堆中创建,又实现了在栈中由编译器管理。继而实现自动释放。省去了我们忘记delete的烦恼。栈中变量sp在自动释放时,执行自己的析构函数,自己的析构函数,管理着我们要被托管的指针。进而实现了指针的自动释放。

上面是自动释放的实现,还有一个问题,在我们被托管类指针中,要调用showAge方法,此时用智能指针是无法无法实现的。即:sp->showAge()无法实现。

如果要调用这个方法,我们可以把我们的->运算符重载

Person* operator->()
{
	return this->person;
}

此时在sp->运算时,返回的是被托管的指针。只要我们把指针返回,即可调用原来的方法。

如果要实现调用showAge。那么需要sp->->showAge()即可,但是编译器看着两个->觉得多余,这边给我们做了自动的编译器优化

此外,我们使用指针,还有一种用法是解引用:(*p).showAge();

Person& operator*()  // 返回值是对对象本体的引用,不是Person。
{
	return *this->person;
}
void test02()
{
	SmartPointer sp(new Person(10));
	sp->showAge();
	(*sp).showAge();
}

这就有点为了讲解运算符重载为了为之而为之了。 但是也基本讲明了一种实现方式和原理。当然新特性中的智能指针没有那么简单哈。


其实直接友元类也可以实现对成员函数的调用。

#pragma once

#include<iostream>
using namespace std;
class SmartPointer;

class Person
{
public :
	friend class SmartPointer;
	Person(int age);
	void showAge();
	~Person();

private :
	int mAge;
};

声明被托管指针时:可以将其智能指针作为友元类。

然后再友类中直接调用即可。

#include "Person.h"

class SmartPointer
{
public:
	SmartPointer(Person* person)
	{
		this->person = person;
	}
#if 0
	Person* operator->()
	{
		return this->person;
	}

	Person& operator*()  // 返回值是对对象本体的引用,不是Person。
	{
		return *this->person;
	}
#endif 
	~SmartPointer()
	{
		if (this->person != NULL)
		{
			delete this->person;
			this->person = NULL;
		}
		cout << "智能指针被释放。" << endl;
	}

	void showAge()
	{
		this->person->showAge();
	}

private:
	Person* person;
};

void test01()
{
	//Person p1(10);  //建立在栈中,函数结束由编译器自动销毁。
	Person *p1 = new Person(10);   // new返回指针类型的对象。
	delete p1;  // 必须手动释放。
}

void test02()
{
	SmartPointer sp(new Person(10));
	//sp->showAge();
	//(*sp).showAge();
	sp.showAge();
}

int main()
{
	//test01();
	test02();

	return EXIT_SUCCESS;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

面试可能会问六:智能指针 的相关文章

  • 智能指针(shared_ptr,unique_ptr)作为函数参数或者返回值时的一些注意事项

    智能指针 shared ptr unique ptr 作为函数参数或者返回值时的一些注意事项 当智能指针作为函数的参数或者返回值时 xff0c 一直在纠结到底是用智能指针对象本身还是用原始指针 Herb Sutter大师的文章很好的解决了这
  • 面试可能会问六:智能指针

    先看一下百度百科的解释 xff1a 指针指针 当类中有指针成员时 xff0c 一般有两种方式来管理指针成员 xff1a 一是采用值型的方式管理 xff0c 每个类对象都保留一份指针指向的对象的拷贝 xff1b 另一种更优雅的方式是使用智能指
  • stl智能指针和boost智能指针对比

    先说说stl中的智能指针auto ptr xff0c 先说说auto ptr的特点 std auto ptr用来管理单个堆内存对象 xff0c 但是独享所有权 xff0c 且不允许赋值和拷贝 xff08 没有重载operator 61 xf
  • C++11智能指针(六):unique_ptr介绍与例子

    本节介绍下c 43 43 11提供的智能指针实现 std unique ptr lt gt 什么是std unique ptrunique ptr lt gt 是c 43 43 11提供的智能指针实现之一 xff0c 用于防止内存泄漏 un
  • c++11新特性之独占指针unique_ptr

    独占智能指针unique ptr 独占智能指针不允许其他智能指针共享内部的指针 可以通过它的构造函数初始化一个独占智能指针对象 但是不允许通过赋值将一个unique ptr赋值给另一个unique ptr unique ptr不允许复制 但
  • Qt 智能指针详细介绍

    1 Qt智能指针概述 Qt 提供了一套基于父子对象的内存管理机制 所以我们很少需要去手动 delete 但程序中不一定所有类都是QObject的子类 这种情况下仍然需要使用一些智能指针 注意 在 Qt 中使用智能指针时 一定要避免发生多次析
  • 共享型智能指针的实现share_pointer

    智能指针是一个类 它产生的是一个类对象 而不是一个原生的指针对象 但是为了减少类对象与针对对象使用的差异性 所以share ptr类故意重载了两种常见的指针操作符 和 gt 从而share ptr与普通指针使用方式一样 简言之 就是shar
  • Qt 中的智能指针

    Qt 中的智能指针 上一篇博客中介绍了 C 11 标准中的提供的智能指针 在 Qt 中也提供了类似的替代功能 并且比 C 11 标准中提供的功能还要强大 所以如果我们使用 Qt 作为基础库 那么就没有必要使用C 11 的智能指针 Qt 的智
  • c++11 智能指针 (std::shared_ptr)(三)

    定义于头文件
  • std:weak_ptr 用法小结。

    http blog csdn net coolmeme article details 43266319 参考了这篇博客 感谢博主的贡献 感谢博主的翻译 不过他写的太多了 我只是记录一下使用方法 原理就不深究了 需要了解其原理的可以自行去那
  • 【Qt】Qt中智能指针

    文章目录 一 QPointer 二 QSharedPointer 2 1 常用操作函数 1 返回此对象所引用的指针的值 2 清除这个QSharedPointer对象 删除它可能对该指针的引用 如果这是最后一个引用 那么指针本身将被删除 3
  • c++11 智能指针 (std::shared_ptr)(一)

    定义于头文件
  • 【C++11智能指针】weak_ptr概述、创建、常用操作、尺寸

    文章目录 1 weak ptr概述 2 weak ptr的创建 2 1 lock 3 weak ptr的常用操作 3 1 use count 3 2 expired 3 3 reset 4 weak ptr的尺寸 1 weak ptr概述
  • [C++11]弱引用智能指针weak_ptr初始化和相关的操作函数

    弱引用智能指针 std weak ptr 可以看做是 shared ptr 的助手 它不管理 shared ptr 内部的指针 std weak ptr 没有重载操作符 和 gt 因为它不共享指针 不能操作资源 所以它的构造不会增加引用计数
  • 智能指针之unique_ptr

    unique ptr实现的是专属所有权语义 用于独占它所指向的资源对象的场合 某个时刻只能有一个unique ptr指向一个动态分配的资源对象 也就是这个资源不会被多个unique ptr对象同时占有 它所管理的资源只能在unique pt
  • C++11智能指针之unique_ptr

    1 智能指针概念 智能指针是基于RAII机制实现的类 模板 具有指针的行为 重载了operator 与operator gt 操作符 可以 智能 地销毁其所指对象 C 11中有unique ptr shared ptr与weak ptr等智
  • 【C++碎碎念】C++11新特性(声明、智能指针、右值引用、lambda表达式)

    目录 一 新类型 二 统一的初始化 三 声明 四 智能指针 五 右值引用 六 Lambda表达式 一 新类型 C 11新增了long long和unsigned long long 以支持64位 或更宽 的整型 新增了类型char16 t
  • C++智能指针详解

    1 概述 我们知道除了静态内存和栈内存外 每个程序还有一个内存池 这部分内存被称为自由空间或者堆 程序用堆来存储动态分配的对象即那些在程序运行时分配的对象 当动态对象不再使用时 我们的代码必须显式的销毁它们 在C 中 动态内存的管理是用一对
  • c++智能指针

    C 智能指针详解 本文系转载 原文出处 诚然原博主总结的非常好 我只是加一些自己觉得需要补充的地方 并且在最后给出目前c 11在智能指针这方面的弥补 一 简介 由于 C 语言没有自动内存回收机制 程序员每次 new 出来的内存都要手动 de
  • C++智能指针之unique_ptr(保姆级教学)

    目录 unique ptr 概述 涉及程序 初始化 手动初始化 std make unique函数 C 14 unique ptr常规操作 不支持操作 该指针不支持拷贝和赋值操作 所以不能拷贝到容器里 移动语义std move releas

随机推荐

  • 整数转换为字符串

    include lt stdio h gt 反转字符串 char reverse char s char temp char p 61 s p指向s的头部 char q 61 s q指向s的尾部 while q 43 43 q q 交换移动
  • 【工具使用】Modbus Poll软件使用详解

    软件介绍 Modbus Poll是一个模拟Modbus协议主机的上位机软件 xff0c 主要用于模拟测试跟其他从机设备通信的过程 与之成套存在的另一个软件 Modbus Slave xff0c 则是模拟Modbus协议从机的上位机软件 该软
  • c++下程序的运行(第3方库的安装及安装gdal)

    C 43 43 安装第三方库 1 概览2 编译 xff0c 首先要熟悉程序编译过程 xff08 预处理 gt 编译 gt 汇编 gt 链接 xff09 2 1 编译流程4步2 1 1 1 预处理2 1 2 2 编译2 1 3 3 汇编2 1
  • 制作IEC101/104报文解析工具

    文章目录 准备 一 IEC101 104协议 二 制作解析工具步骤 1 建立协议族 2 建立协议 3 建立术语 4 建立报文块 5 建立报文解析规则 总结 准备 这里是基于 在线解析二进制报文 文章中介绍的物联网助手来快速搭建IEC101
  • PHP各版本技术特性(标贝科技)

    文章目录 PHP8JIT流程配置测试小结 match表达式 PHP7HugepageHugepage简介Hugepage配置 Opcache file cacheOpcache file cache简介Opcache file cache配
  • vue、springboot集成websocket跨域问题解决

    由于浏览器连接的是服务器上的websocket xff0c 导致出现了如下跨域错误 xff1a The value of the 39 Access Control Allow Origin 39 header in the respons
  • 动态库学习

    总结一 xff1a 动态库 前言 我们知道程序编译链接经常使用动态 xff0c 同时我们可能还知道 xff0c 动态库时程序运行时加载的 但是动态库到底有什么作用 xff0c 如何生成 如何加载等 xff0c 我们却很少关注 接下来 xff
  • Python学习第一次问题笔记:vscode 运行python代码没有输出(Code runner)

    目录 问题 xff1a 解决方案 xff1a 原因一 xff1a 原因二 xff1a 问题 xff1a 新安装Visual Studio Code后 xff0c 在其上进行第一次代码运行时 xff0c 会出现只在终端中显示代码结果 xff0
  • 标准差分进化算法matlab程序实现

    终于开始了研究生阶段的学习生活 xff0c 繁琐的入学相关事宜也处理得差不多了 在9月5号 xff0c 我们实验室召开了第一次小组会议 xff0c 导师也相继给我们指定了各自的研究方向 xff0c 不出意外 xff0c 我接下来将围绕智能优
  • 《图解深度学习》学习笔记(一)

    第一章 绪论 监督学习 xff1a 需要基于输入数据及其期望输出 xff0c 通过训练从数据中提取通用信息或特征信息 特征值 xff0c 以此得到预测模型 这里的特征值是指根据颜色和边缘等认为定义的提取方法从训练样本中提取的信息 xff08
  • 3D点云基础知识(一)-初始入门-知乎整理(一)

    本文基于如下知乎文章 xff0c 调整部分内容整理输出 xff0c 一为梳理基础知识 xff0c 二为致敬原作 作者 xff1a Mr 苍雪 链接 xff1a https zhuanlan zhihu com p 344635951 来源
  • Open3D处理点云数据(一)点云文件读取、写入、显示

    import open3d as o3d import numpy as np pcd 61 o3d geometry PointCloud pcd类型的数据 np points 61 np random rand 100 3 随机生成点云
  • Ubuntu非管理员root安装ninja:解决RuntimeError: Ninja is required to load C++ extensions错误

    服务器是共用的 xff0c 所以无法使用sudo apt get 命令快速安装 只能自己下载git上的源代码然后编译 xff0c 装在自己的私人目录下 否则 sudo apt get 安装很容易 xff0c 55555555 Ninja是一
  • Elasticsearch相似度算分TF-IDF BM25(标贝科技)

    欢迎体验标贝语音开放平台 地址 xff1a https ai data baker com source 61 qaz123 xff08 注 xff1a 填写邀请码hi25d7 xff0c 每日免费调用量还可以翻倍 xff09 控制相关度
  • 【K210】K210学习笔记五——串口通信

    K210 K210学习笔记五 串口通信 前言K210如何进行串口通信K210串口配置K210串口发送相关定义K210串口接收相关定义K210串口发送接收测试 完整源码 前言 本人大四学生 xff0c 电赛生涯已经走到尽头 xff0c 一路上
  • C++类与对象笔记十二:运算符重载三:递增运算符重载

    先看看系统自带的递增运算符 43 43 递增运算符重载 43 43 xff1b a 43 43 43 43 a int a 61 10 cout lt lt 43 43 a lt lt endl 11 先加 xff0c 后输出 cout l
  • C++类与对象笔记十四:多态六:虚析构和纯虚析构

    多态使用时 xff0c 如果子类中有属性开辟到堆区 xff0c 那么父类指针在释放时无法调用子类的析构代码 即 xff1a 父类指针无法调用子类实例对象内的析构函数 造成堆区内存泄漏 解决方案 将父类中的析构函数改为虚析构或者纯虚析构 虚析
  • PCL笔记九:采样一致性

    模型拟合 xff1f 采样一致性的目的 xff1a 用于排除错误的样本 基于采样一致性算法的应用主要是对点云进行分割 xff0c 根据不同设定的几何模型 xff0c 估计对应的几何模型的参数 xff0c 在一定允许误差范围内分割出在模型上的
  • ubuntu下安装gfortran

    找官网 xff1a GFortranBinaries GCC Wiki 找到GNU Linux 找到Download xff0c 点击蓝色链接下载 此外有installtion instructions安装步骤 Gfortran Binar
  • 面试可能会问六:智能指针

    先看一下百度百科的解释 xff1a 指针指针 当类中有指针成员时 xff0c 一般有两种方式来管理指针成员 xff1a 一是采用值型的方式管理 xff0c 每个类对象都保留一份指针指向的对象的拷贝 xff1b 另一种更优雅的方式是使用智能指