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; // 1



    cout << "=====================" << 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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于深度学习的中文情感分类 - 卷积神经网络 情感分类 情感分析 情感识别 评论情感分类 计算机竞赛

文章目录 1 前言2 情感文本分类2.1 参考论文2.2 输入层2.3 第一层卷积层&#xff1a;2.4 池化层&#xff1a;2.5 全连接softmax层&#xff1a;2.6 训练方案 3 实现3.1 sentence部分3.2 filters部分3.3 featuremaps部分3.4 1max部分3.5 concat1max部分3.6 关键代码 4 实现效果4.…

【HTML/CSS学习】margin和padding的区别

1. margin margin&#xff08;外边距&#xff09;属性定义元素周围的空间。 margin主要在元素的外部创建空白区域&#xff0c;用于分隔元素与其相邻元素之间的距离。 用处&#xff1a;可以用于调整两个元素之间的间隔。 2. padding padding&#xff08;填充&#xff09;定义…

IDE的组成

集成开发环境&#xff08;IDE&#xff0c;Integrated Development Environment &#xff09;是用于提供程序开发环境的应用程序&#xff0c;一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务…

拿下国家级信创认证 中科驭数KPU SWIFT-2200N成为国内首款满足金融业严苛要求的DPU产品

近日&#xff0c;中科驭数KPU SWIFT-2200N低时延DPU卡&#xff0c;在中国人民银行旗下金融信创生态实验室完成测试并取得测试报告&#xff0c;这意味着中科驭数低时延网络代表性产品的应用领域从证券进一步拓展到了银行业&#xff0c;成为国内首款满足金融行业严苛要求的DPU产品…

iis前端代理后台tomcat

1)tomcat服务器配置运行好&#xff0c;服务地址位于 localhost:8080/wechat 2)iis 绑定了域名 api.abc.com 希望访问 api.abc.com/wechat时&#xff0c;实际由tomcat的服务处理; 3)iis上需要添加组件 requestRouter_amd64.msi rewrite_amd64_zh-CN.msi 4)iis进行相关配置…

记录linux运行服务提示报错/bin/java: 没有那个文件或目录

描述&#xff1a;在执行jar启动命令时候提示 没有/bin/java 这个文件或者目录&#xff1b;然后我vi /usr/bin/java&#xff0c;是存在该文件的&#xff1b;那到底是什么问题呢&#xff0c;该不是没有创建软连接吧&#xff1f; 1、执行下述命令先测试下软链接是否有创建 ln -s …

用软件模拟IPC的RTSP流,对接烟火识别算法服务,做实时的烟火检测、人员入侵检测、抽烟检测等算法

最近在研发烟火识别的算法&#xff0c;想要检验算法集成到视频分析服务之后的效果&#xff0c;发现线上的摄像机很难发现火情&#xff0c;有的很长时间都不会有检测的结果&#xff0c;于是我就需要用已经被检验过的视频文件&#xff0c;模拟一路IPC的RTSP流&#xff0c;来测试烟…

jenkins如何安装?

docker pull jenkins/jenkins:lts-centos7-jdk8 2.docker-compose.yml version: 3 services:jenkins:image: jenkins/jenkins:lts-centos7-jdk8container_name: my-jenkinsports:- "8080:8080" # 映射 Jenkins Web 界面端口volumes:- jenkins_home:/var/jenkins_h…

【MySQL数据库】初识MySQL数据库、安装MySQL

文章目录 前言一、什么是 MySQL&#xff1f;二、MySQL 的强大之处三、Ubuntu安装MySQL步骤 1: 更新包列表步骤 2: 安装 MySQL步骤 3: 启动 MySQL 服务步骤 4: 验证 MySQL 安装步骤 5: 确保 MySQL 安全性 总结 前言 在今天的数字化世界中&#xff0c;数据是企业和个人的重要资产…

matlab 中的基本绘图指令与字符串操作指令

字符串指令 创建字符串 使用单引号将字符序列括起来创建字符串使用单引号创建的字符串是一个字符数组&#xff0c;每个字符都被视为一个独立的元素 可以通过索引访问每个字符使用双引号创建的字符串是一个字符串数组&#xff0c;整个字符串被视为一个元素 无法通过索引访问单个…

【SEC 学习】美化 Linux 终端

一、步骤 1. 进入 /etc/bash.bashrc vim /etc/bash.bashrc2. 重新加载 bash.bashrc source /etc/bash.bashrc二、各参数指标 符号含义\u当前用户的账号名称\h仅取主机的第一个名字&#xff0c;如上例&#xff0c;则为fc4&#xff0c;.linux则被省略\H完整的主机名称。例如&…

一文详解防御DDoS攻击的几大有效办法

伴随互联网的飞速发展&#xff0c;网络安全问题变得越来越突出&#xff0c;其中最常见的就是DDoS攻击&#xff0c;也就是分布式拒绝服务攻击。DDoS攻击者利用计算机或其他设备的协作&#xff0c;以发送大量请求的方式导致目标超负荷&#xff0c;导致不能正常运转或“宕机”。以…

【Linux】NTP服务器配置、时间修改

查看当前系统时间date修改当前系统时间date -s "2018-2-22 19:10:30"查看硬件时间hwclock --show修改硬件时间hwclock --set --date "2018-2-22 19:10:30"同步系统时间和硬件时间hwclock --hctosys保存时钟clock –w1.设置NTP Server服务检查系统是否安装n…

医学专题--多组学在病原微生物感染中的研究思路

研究背景 病原微生物是指可以侵犯人和动物&#xff0c;引起感染甚至传染病的微生物&#xff0c;包括病毒、细菌、真菌、立克次体、寄生虫等。在我国&#xff0c;感染性疾病占所有疾病的50%以上&#xff0c;每年约1300万儿童死于感染性疾病&#xff1b;而临床上感染性疾病患者中…

BUUCTF qr 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 这是一个二维码&#xff0c;谁用谁知道&#xff01; 密文&#xff1a; 下载附件&#xff0c;得到一张二维码图片。 解题思路&#xff1a; 1、这是一道签到题&#xff0c;扫描二维码得到flag。 flag&#xff1a;…

calloc、malloc、realloc函数的区别及用法

三者都是分配内存&#xff0c;都是stdlib.h库里的函数&#xff0c;但是也存在一些差异。 &#xff08;1&#xff09;malloc函数。其原型void *malloc(unsigned int num_bytes)&#xff1b; num_byte为要申请的空间大小&#xff0c;需要我们手动的去计算&#xff0c;如int *p …

3 tensorflow构建的模型详解

上一篇&#xff1a;2 用TensorFlow构建一个简单的神经网络-CSDN博客 1、神经网络概念 接上一篇&#xff0c;用tensorflow写了一个猜测西瓜价格的简单模型&#xff0c;理解代码前先了解下什么是神经网络。 下面是百度AI对神经网络的解释&#xff1a; 这里不赘述太多概念相关的…

linux 系统编程复习07-信号

1 复习目标 了解信号中的基本概念熟练使用信号相关的函数参考文档使用信号集操作相关函数熟练使用信号捕捉函数signal熟练使用信号捕捉函数sigaction熟练掌握使用信号完成子进程的回收 信号介绍 信号的概念 信号是信息的载体&#xff0c;Linux/UNIX 环境下&#xff0c;古老…

【计算机网络】三次握手 四次挥手

目录 1.三次握手 2.四次挥手 3.总结 三次握手和四次挥手是有连接特有的。三次握手&#xff0c;四次挥手指的是TCP有连接特点的中的步骤。建立连接(三次握手)&#xff0c;断开连接(四次挥手)。建立连接操作一般都是客户端主动发起&#xff0c;断开连接操作客户端和服务器都可…

Linux shell编程学习笔记17:for循环语句

Linux Shell 脚本编程和其他编程语言一样&#xff0c;支持算数、关系、布尔、字符串、文件测试等多种运算&#xff0c;同样也需要进行根据条件进行流程控制&#xff0c;提供了if、for、while、until等语句。 之前我们探讨了if语句&#xff0c;现在我们来探讨for循环语句。 Li…