【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 智能指针。

相关推荐
EatFan4 小时前
2026 Rust 后端技术栈选型:Axum 0.8 + Tokio + SQLx 全链路怎么搭
开发语言·后端·rust·tokio·serde·axum·sqlx
外收内放4 小时前
Python基础语法练习题(59-原始版本与优化版本)
开发语言·python
2401_888859714 小时前
STM32H733 MPU、AXI、FMC学习
java·开发语言·stm32·spring
泡海椒4 小时前
JQuick-Excel 实战:用 STYLE 配置单元格与区域样式
开发语言·python·excel
Sarvartha13 小时前
final 关键字
java·开发语言
程序员Sunday13 小时前
JavaScript 事件循环面试题,宏任务与微任务怎么执行|Sunday面试指南
开发语言·javascript·面试·校招·事件循环·程序员sunday
Quz14 小时前
QML 动画选择:GIF与Lottie 的区别,以及 Qt 6.8 与 6.11 的 Lottie 实现差异
qt
zhangzeyuaaa14 小时前
Ruby 多线程、GVL(GIL)与 Mutex 完全指南
开发语言·前端·ruby
谢亮_vipxieliang15 小时前
用 PHP 构建轻量级 REST API:从路由到鉴权的完整实践
开发语言·后端·php
思无邪6615 小时前
用 AI 做 JS 逆向:从抓包到复现的完整方法论
开发语言·javascript·人工智能