【Qt】std::shared_ptr<>与std::make_shared<>

cpp 复制代码
std::shared_ptr<int>

这是 C++11 引入的:

txt 复制代码
智能指针(Smart Pointer)

完整理解:

txt 复制代码
一个"自动管理 int 对象生命周期"的指针

它属于:

cpp 复制代码
#include <memory>

中的内容。


一、先看传统指针的问题

传统写法:

cpp 复制代码
int* p = new int(10);

这里:

  • new
    → 在堆上申请内存

返回:

txt 复制代码
int*

也就是普通指针。


问题:容易内存泄漏

你必须手动:

cpp 复制代码
delete p;

否则:

txt 复制代码
内存泄漏

例如:

cpp 复制代码
void test()
{
    int* p = new int(10);

    return; // 忘记delete
}

这块内存永远回收不了。


二、shared_ptr 的作用

于是 C++11 提供:

cpp 复制代码
std::shared_ptr

用于:

txt 复制代码
自动释放内存

三、这句代码是什么意思

cpp 复制代码
std::shared_ptr<int> p;

拆开看:


1. shared_ptr

表示:

txt 复制代码
共享所有权智能指针

意思:

txt 复制代码
多个指针可以共同拥有同一个对象

内部使用:

txt 复制代码
引用计数

管理生命周期。


2. <int>

模板参数。

表示:

txt 复制代码
它管理的是 int 类型对象

类似:

cpp 复制代码
std::vector<int>

里的 <int>


3. 整体意思

cpp 复制代码
std::shared_ptr<int> p;

等价理解:

txt 复制代码
定义一个"管理 int 对象"的智能指针

四、最常见正确写法

通常这样创建:

cpp 复制代码
auto p = std::make_shared<int>(10);

意思:

txt 复制代码
在堆上创建 int(10)
并用 shared_ptr 管理

五、内部发生了什么

cpp 复制代码
auto p = std::make_shared<int>(10);

大致等价于:

cpp 复制代码
int* raw = new int(10);

但:

txt 复制代码
shared_ptr 会自动 delete

你不需要:

cpp 复制代码
delete

六、使用方式


读取值

cpp 复制代码
std::cout << *p;

输出:

txt 复制代码
10

因为:

cpp 复制代码
*p

是解引用。


修改值

cpp 复制代码
*p = 20;

七、shared(共享)是什么意思

这是 shared_ptr 最核心部分。


多个 shared_ptr 指向同一对象

cpp 复制代码
auto p1 = std::make_shared<int>(100);

auto p2 = p1;

此时:

txt 复制代码
p1 和 p2
共同拥有同一个 int

内存里:

txt 复制代码
      +--------+
p1 -->| int100 |
p2 -->|        |
      +--------+

八、引用计数

shared_ptr 内部有:

txt 复制代码
引用计数(Reference Count)

创建时

cpp 复制代码
auto p1 = std::make_shared<int>(100);

计数:

txt 复制代码
1

拷贝后

cpp 复制代码
auto p2 = p1;

计数:

txt 复制代码
2

一个对象销毁

cpp 复制代码
p2 离开作用域

计数:

txt 复制代码
1

最后一个销毁

txt 复制代码
计数=0

自动:

cpp 复制代码
delete

释放内存。


九、例子

cpp 复制代码
#include <iostream>
#include <memory>

int main()
{
    auto p1 = std::make_shared<int>(10);

    {
        auto p2 = p1;

        std::cout << p1.use_count() << std::endl;
    }

    std::cout << p1.use_count() << std::endl;
}

输出:

txt 复制代码
2
1

十、为什么推荐 make_shared

推荐:

cpp 复制代码
auto p = std::make_shared<int>(10);

不推荐:

cpp 复制代码
std::shared_ptr<int> p(new int(10));

因为:


make_shared 优点

1. 性能更好

一次内存分配。


2. 更安全

避免异常导致泄漏。


3. 代码更简洁


十二、如何判断为空

cpp 复制代码
if (b)
{
    // 非空
}
else
{
    // 空
}

十三、shared_ptr 内存结构

内部大概:

txt 复制代码
shared_ptr
   │
   ├── 指向对象
   │
   └── 引用计数控制块

例如:

txt 复制代码
+----------------+
| control block  |
| ref_count = 2  |
+----------------+
         |
         v
     +-------+
     | int10 |
     +-------+

十四、shared_ptr 最大问题


循环引用

例如:

cpp 复制代码
class A
{
    shared_ptr<B> b;
};

class B
{
    shared_ptr<A> a;
};

结果:

txt 复制代码
A 引用 B
B 引用 A

引用计数永远不为 0。

导致:

txt 复制代码
内存泄漏

解决方法

使用:

cpp 复制代码
std::weak_ptr

打破循环引用。


十五、智能指针三兄弟


1. unique_ptr

独占所有权。

txt 复制代码
一个对象只能有一个主人

不能复制。

性能最好。


2. shared_ptr

共享所有权。

可多个指针共享。

有引用计数开销。


3. weak_ptr

弱引用。

不增加引用计数。

用于:

  • 观察对象
  • 打破循环引用

十六、现代 C++ 推荐

现代 C++:

txt 复制代码
尽量不要直接 new/delete

推荐:

cpp 复制代码
make_unique
make_shared

RAII 自动管理资源。


十七、Qt 中的对应关系

Qt 里类似:

STL Qt
shared_ptr QSharedPointer
weak_ptr QWeakPointer
unique_ptr QScopedPointer

不过现代 Qt 项目:

很多人直接使用 STL 智能指针。

相关推荐
知无不研33 分钟前
lambda表达式的使用(3)
开发语言·c++·lambda
cfm_29141 小时前
SpringAI + Ollama 本地大模型
java·开发语言·人工智能·语言模型
C++ 老炮儿的技术栈2 小时前
基于Qt实现轻量化本地音乐播放器
开发语言·c++·qt·c·播放器·音乐
qq_448011162 小时前
C语言中的柔性数组
c语言·开发语言·柔性数组
小白学大数据2 小时前
长周期爬虫的数据一致性:断点续爬 + 事务回滚保障采集质量
开发语言·爬虫·测试工具
zlinear数据采集卡3 小时前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
Poo_Chai3 小时前
QT emit信号后完整处理流程,包括槽函数响应流程
java·开发语言·数据库
瑞码空间3 小时前
Java 图形界面(GUI)完整知识点手册
java·开发语言·图形界面·swing
小努蛋4 小时前
linux编译openresty异常问题,lua_cjson.c:706:5: 错误: ‘for‘ 循环初始化声明只在 C99 或 C++ 模式下允许
开发语言·lua·openresty
qz_Serene4 小时前
C++:类和对象(上)
开发语言·c++