C++进阶语法——智能指针【学习笔记(五)】

文章目录

      • 1、智能指针简介
        • 1.1 原始指针(raw pointer)的⼀些问题
        • 1.2 智能指针(smart pointers)
      • 2、智能指针(smart pointers)——unique_ptr
        • 2.1 unique_ptr 的声明
        • 2.2 unique_ptr 的函数
        • 2.3 ⾃定义类型使⽤ unique_ptr
        • 2.4 unique_ptr 不⽀持拷⻉、赋值
        • 2.5 使⽤make_unique初始化(C++14标准)
        • 代码:
      • 3、智能指针(smart pointers)——shared_ptr
        • 3.1 shared_ptr的声明
        • 3.2 shared_ptr的函数
        • 3.3 ⾃定义类型使⽤shared_ptr
        • 3.4 vector和复制操作
        • 3.5 使⽤make_shared初始化(C++11标注)
        • 代码:

1、智能指针简介

1.1 原始指针(raw pointer)的⼀些问题

C++ 提供了内存管理的绝对⾃由度
------->• 分配
------->• 释放
------->• 声明周期管理
⼀些潜在严重问题
------->• 未初始化的指针(wild pointer),也就是野指针,可指向内存的任何位置
------->• 内存泄漏(memory leak),可能因为没有及时释放分配的内存空间
------->• 悬空指针(dangling pointer):指针指向已经释放的对象
所有权(ownership),引入智能指针
------->• 谁拥有指针?
------->• 何时可以删除指针?

1.2 智能指针(smart pointers)

• 也是对象
• 只能指向堆上分配的内存
⽤完后会⾃动删除
• 遵循RAII(资源获取即初始化)原则,对资源的申请释放,是一种成对操作的封装
• 几种C++ 智能指针:
------->• Unique pointers (unique_ptr)
------->• Shared pointers (shared_ptr)
------->• Weak pointers (weak_ptr)
------->• Auto pointers (auto_ptr) (已弃⽤)

  • 导入 #include <memory>
  • 在类模板(class templates)中定义
    • 对原始指针做了封装
    • 重载的操作符
      • 解引⽤(*)
      • 成员选择(->)
      • 不⽀持算数操作符(++, — —等)

创建智能指针的具体实例如下,smart_pointer 可以换成上面提到的 unique_ptr,shared_ptr,weak_ptr,ptr 是指向 Type 类别的智能指针,当运行完 {} 里面的程序时,会自动调用析构函数,会帮助我们处理堆上分配的内存空间,

在这里插入图片描述

2、智能指针(smart pointers)——unique_ptr

  • unique_ptr<T> ptr_name
    • 指向heap堆上类型 T 的对象
    • 唯⼀(unique),多个 unique_ptr 不可以指向同⼀个对象
    • 拥有指向对象的唯⼀所有权
    • 不可以复制或赋值,但可以移动
    • 指针使⽤完毕,被指向的对象会⾃动释放销毁
2.1 unique_ptr 的声明

在这里插入图片描述

2.2 unique_ptr 的函数

在这里插入图片描述

2.3 ⾃定义类型使⽤ unique_ptr

在这里插入图片描述

2.4 unique_ptr 不⽀持拷⻉、赋值

std::move(p1):转移p1拥有的所有权,容器 vec 拥有堆上面对象的所有权,p1 会设置为空指针,

在这里插入图片描述

2.5 使⽤make_unique初始化(C++14标准)

make_unique 的作用也是在堆上创建的内存空间,
auto 关键字是编译器根据 make_unique 的返回值自动帮我们判断数据类型,

在这里插入图片描述

代码:
#include <iostream>
#include <vector>
#include <string>
#include <memory>using namespace std;class Account
{
private:string name {"account"};double balance {0.0};
public:Account(string name = "none", double balance = 0.0);~Account();bool deposit(double amount);void printInfo() const;double getBalance();
};Account::Account(string name, double balance):name {name}, balance {balance}
{cout << "构造函数,name: " << name << endl;
}Account::~Account()
{cout << "析构函数,name: " << name << endl;
}
bool Account::deposit(double amount)
{balance += amount;return true;
}void Account::printInfo() const
{cout << "name: " << name << ", balance: " << balance << endl;
}
double Account::getBalance()
{return balance;
}int main()
{// Account alice_account {"Alice", 1000.0}; // 构造函数和析构函数都会被调用// Account * bob_account = new Account {"Bob", 2000.0}; // 只有构造函数被调用// delete bob_account; // 析构函数被调用// unique_ptr<Account> p1 {new Account {"jams", 1000.0}}; // 构造函数和析构函数都会被调用// auto p2 = make_unique<Account>("mike", 2000.0); // 构造函数和析构函数都会被调用// unique_ptr<Account> p3;// // p3 = p2; // 报错,因为unique_ptr不允许拷贝,只能移动// p3 = move(p2); // p2 会被置为null,即空指针// if (! p2)//     cout << "p2 is null" << endl;// auto p4 = make_unique<Account>("Helen", 3000.0);// p4->deposit(1000.0);// p4->printInfo(); // 调用成员函数vector<unique_ptr<Account>> accounts;accounts.push_back( make_unique<Account>("alice",1000));accounts.push_back( make_unique<Account>("bob",500));accounts.push_back( make_unique<Account>("mike",1000));for (const auto &acc: accounts) cout << acc->getBalance() << endl;return 0;
}

3、智能指针(smart pointers)——shared_ptr

  • shared_ptr<T> ptr_name
    • 指向heap堆上类型为 T 的对象
    • 不唯⼀,多个shared_ptr可以指向同⼀个对象
    • 被管理对象的所有权在多个shared_ptr中共享
    • 可以复制或赋值
    • 可以移动
    • 引⽤计数(reference count)为0,被指向的对象会⾃动释放销毁
3.1 shared_ptr的声明

当超出 {} 的作用域后,堆上的对象也会自动销毁,

在这里插入图片描述

3.2 shared_ptr的函数

use_count():返回引用计数的值,也就是当前堆上的对象被多少 shared_ptr 管理,
p1.reset() 并没有释放 p1 所指向的对象,因为 p2 还在指向这个对象,

在这里插入图片描述

3.3 ⾃定义类型使⽤shared_ptr

在这里插入图片描述

3.4 vector和复制操作

在这里插入图片描述

3.5 使⽤make_shared初始化(C++11标注)

不再使用关键字 new,编译器也可以生成更高效的执行代码,

在这里插入图片描述

代码:
#include <iostream>
#include <vector>
#include <string>
#include <memory>using namespace std;class Account
{
private:string name {"account"};double balance {0.0};
public:Account(string name = "none", double balance = 0.0);~Account();void print() const;
};Account::Account(string name, double balance):name {name}, balance {balance}
{cout << "构造函数,name: " << name << endl;
}Account::~Account()
{cout << "析构函数,name: " << name << endl;
}
void Account::print() const
{cout << "name: " << name << ", balance: " << balance << endl;
}void test_func(shared_ptr<Account> p)
{cout << "p.use_count(): " << p.use_count() << endl; // 2
}int main()
{// cout << "=====================" << endl;// shared_ptr<int> p1 {new int {100}};// cout << "p1.use_count(): " << p1.use_count() << endl; // 1// shared_ptr<int> p2 {p1}; // 共享所有权// cout << "p1.use_count(): " << p1.use_count() << endl; // 2// p1.reset(); // 释放所有权,但是不会销毁对象,因为p2还在使用// cout << "p1.use_count(): " << p1.use_count() << endl; // 0// cout << "p2.use_count(): " << p2.use_count() << endl; // 1// cout << "=====================" << endl;// shared_ptr<Account> p1 = make_shared<Account>("Alice", 1000.0);// test_func(p1);// cout << "p1.use_count(): " << p1.use_count() << endl; // 2// {//     shared_ptr<Account> p2 = p1;//     cout << "p2.use_count(): " << p2.use_count() << endl; // 3//     {//         shared_ptr<Account> p3 = p1;//         cout << "p3.use_count(): " << p3.use_count() << endl; // 4//         p1.reset();//     }//     cout << "p1.use_count(): " << p1.use_count() << endl; // 2//     cout << "p2.use_count(): " << p2.use_count() << endl; // 2// }// cout << "p1.use_count(): " << p1.use_count() << endl; // 1cout << "=====================" << endl;shared_ptr<Account> p1 = make_shared<Account>("Alice", 1000.0);shared_ptr<Account> p2 = make_shared<Account>("Bob", 2000.0);shared_ptr<Account> p3 = make_shared<Account>("Charlie", 3000.0);vector<shared_ptr<Account>> accounts;accounts.push_back(p1);accounts.push_back(p2);accounts.push_back(p3);for (const auto &p: accounts){p->print();cout << "p.use_count(): " << p.use_count() << endl; // 1}return 0;
}

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

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

相关文章

0004net程序设计-抗疫物资

文章目录 **摘** **要**目 录系统设计开发环境 摘 要 近些年来&#xff0c;随着科技的飞速发展&#xff0c;互联网的普及逐渐延伸到各行各业中&#xff0c;给人们生活带来了十分的便利&#xff0c;抗疫物资管理系统利用计算机网络实现信息化管理&#xff0c;使整个抗疫物资管理…

Linux下GPIO和看门狗应用编程

文章目录 GPIO应用编程看门狗应用编程 GPIO应用编程 应用层操控硬件可以通过操作这些硬件的设备文件来进行&#xff0c;设备文件是各种硬件设备向应用层提供的一个接口&#xff0c;应用层通过对设备文件的I/O操作来操控硬件设备。设备文件通常在/dev/目录下&#xff0c;该目录…

Yolo-Z:改进的YOLOv5用于小目标检测

目录 一、前言 二、背景 三、新思路 四、实验分析 论文地址&#xff1a;2112.11798.pdf (arxiv.org) 一、前言 随着自动驾驶汽车和自动驾驶赛车越来越受欢迎&#xff0c;对更快、更准确的检测器的需求也在增加。 虽然我们的肉眼几乎可以立即提取上下文信息&#xff0c;即…

延迟队列实现方案总结

日常开发中&#xff0c;可能会遇到一些延迟处理的消息任务&#xff0c;例如以下场景 ①订单支付超时未支付 ②考试时间结束试卷自动提交 ③身份证或其他验证信息超时未提交等场景。 ④用户申请退款&#xff0c;一天内没有响应默认自动退款等等。 如何处理这类任务&#xff0c;最…

MAC缓解WebUI提示词反推

当前环境信息&#xff1a; 在mac上安装好stable diffusion后&#xff0c;能做图片生成了之后&#xff0c;遇到一些图片需要做提示词反推&#xff0c;这个时候需要下载一个插件&#xff0c;参考&#xff1a; https://gitcode.net/ranting8323/stable-diffusion-webui-wd14-tagg…

66 内网安全-域横向批量atschtasksimpacket

目录 演示案例:横向渗透明文传递at&schtasks 案例2-横向渗透明文HASH传递atexec-impacket案例3-横向渗透明文HASH传递批量利用-综合案例5-探针主机域控架构服务操作演示 传递攻击是建立在明文和hash值的一个获取基础上的攻击&#xff0c;也是在内网里面常见协议的攻击&…

一道简单的C#面试题

试题&#xff1a; 抽顺序问题&#xff1a;有10位面试者&#xff0c;需要随机抽号面试。 1&#xff09;总共十个号数&#xff0c;用数组表示&#xff1b; 2&#xff09;每一位面试者输入1开始抽签&#xff0c;然后得到抽签号&#xff0c;输入2结束抽签&#xff1b; 3&#x…

Linux玩物志:好玩却无用的软件探秘

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; &#x1f354;前言&#xff1a; 我们已经学习了yum指令&#xff0c;可以在Linux中安装一些软件的指令。下面我们就盘点一些可玩性很高但是却没有什么用的软件&#xff0c;在枯燥的学习中增添一丝乐趣&#xff01; For…

CSS宽度100%和宽度100vw之间有什么不同?

vw和vh分别代表视口宽度和视口高度。 使用width: 100vw代替的区别在于width: 100%&#xff0c;虽然100%将使元素适合所有可用空间&#xff0c;但视口宽度具有特定的度量&#xff0c;在这种情况下&#xff0c;可用屏幕的宽度 。 如果设置样式body { margin: 0 }&#xff0c;则1…

2000-2021年上市公司产融结合度量数据

2000-2021年上市公司产融结合度量数据 1、时间&#xff1a;2000-2021年 2、指标&#xff1a;股票代码、年份、是否持有银行股份、持有银行股份比例、是否持有其他金融机构股份、产融结合 3、来源&#xff1a;上市公司年报 4、范围&#xff1a;上市公司 5、样本量&#xff…

gRPC源码剖析-Builder模式

一、Builder模式 1、定义 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的的表示。 2、适用场景 当创建复杂对象的算法应独立于该对象的组成部分以及它们的装配方式时。 当构造过程必须允许被构造的对象有不同的表示时。 说人话&#xff1a…

java基础篇-环境变量

java基础 编程学习的关键点、重点1.环境变量设置待续 编程学习的关键点、重点 输入输出 Java语言、C语言、Python语言、甚至SQL语言&#xff0c;都需要实战、做大量输入输出等 1.环境变量设置 1.下载jdk安装 jdk官网下载直达链接&#xff1a;https://www.oracle.com/java/te…

2023香港秋灯展丨移远通信闪耀亮相,开启Matter生态互联新篇章

10月27日&#xff0c;2023香港国际秋季灯饰展于香港会议展览中心正式开幕。 移远通信携最新一站式Matter解决方案、Wi-Fi模组&#xff0c;以及多款代表前沿技术的智能灯具、插座等终端重磅亮相。同时&#xff0c;公司产品总监丁子文围绕“Matter生态互联新篇章”主题发表演讲&a…

深度学习之基于YoloV8的行人跌倒目标检测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、行人跌倒目标检测系统四. 总结 一项目简介 世界老龄化趋势日益严重&#xff0c;现代化的生活习惯又使得大多数老人独居&#xff0c;统计数据表…

Zynq UltraScale+ XCZU7EV 纯VHDL解码 IMX214 MIPI 视频,2路视频拼接输出,提供vivado工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 MIPI 编解码方案3、本 MIPI CSI2 模块性能及其优越性4、详细设计方案设计原理框图IMX214 摄像头及其配置D-PHY 模块CSI-2-RX 模块Bayer转RGB模块伽马矫正模块VDMA图像缓存Video Scaler 图像缓存DP 输出 5、vivado工程详解PL端FPGA硬件设计…

SurfaceFliger绘制流程

前景提要&#xff1a; 当HWComposer接收到Vsync信号时&#xff0c;唤醒DisSync线程&#xff0c;在其中唤醒EventThread线程&#xff0c;调用DisplayEventReceiver的sendObjects像BitTub发送消息&#xff0c;由于在SurfaceFlinger的init过程中创建了EventThread线程&#xff0c…

Android环境变量macOS环境变量配置

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览macOS基础知识 三、设置环境变量3.1 终…

Spring两大核心之一:AOP(面向切面编程)含设计模式讲解,通知类型切点;附有案例,实现spring事务管理

模拟转账业务 pom.xml <dependencies><!--spring--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.29</version></dependency><!--lombok-->…

物联网二维码核销盒对接文档

核销盒是干嘛的&#xff1f; 1.在某些场景下快速核销订单或打卡签到等&#xff0c;通过核销盒能快速将订单信息发送到后端进行处理。 一&#xff0c;首先你需要有一台核销设备&#xff0c;也就是核销盒。 二&#xff0c;通过接口激活或更新核销盒 ​​​​​​​ 简要描述 激…

2.Vue — 模板语法、数据绑定、el与data的写法、数据代理

文章目录 一、模板语法1.1 插值语法1.2指令语法 二、数据绑定语法2.1 单向数据绑定2.2 双向数据绑定 三、el与data的两种写法3.1 el3.2 data 四、数据代理4.1 Object.defineProperty4.2 Vue数据代理4.2.1 展示数据代理4.2.2 Vue数据代理 一、模板语法 root容器里面的代码被称为…