0

0

C++中std::shared_ptr的别名构造函数(Aliasing Constructor)有什么妙用? (子对象共享)

冰火之心

冰火之心

发布时间:2026-02-18 14:32:31

|

355人浏览过

|

来源于php中文网

原创

shared_ptr别名构造函数签名是shared_ptr(const shared_ptr& r, t* ptr),不接管ptr所有权而复用r的控制块;普通构造则新建控制块并独占资源管理。

c++中std::shared_ptr的别名构造函数(aliasing constructor)有什么妙用? (子对象共享)

shared_ptr别名构造函数怎么写,和普通构造差在哪

别名构造函数的签名是 shared_ptr<t>(const shared_ptr<u>& r, T* ptr)</u></t>,关键在第二个参数不是新分配的内存,而是指向 r 所管理对象内部某个子对象(比如成员、数组元素、转型后的地址)的裸指针。

它不接管 ptr 的所有权,只共享 r 的引用计数;ptr 的生命周期完全绑定到 r 上。这点和 shared_ptr<t>(new T)</t>make_shared<t>()</t> 有本质区别——后者自己管内存,前者只是“借个视图”。

  • 普通构造:新资源、新控制块、独立生命周期
  • 别名构造:零额外分配、复用原控制块、生命周期严格从属

常见错误现象:shared_ptr<int>(sp, &sp.get()->val)</int> 看似合理,但如果 spshared_ptr<widget></widget>,而 val 是非 trivial 类型且被 move 走,这个 &val 就可能悬空——别名本身不阻止原对象内部状态变化。

典型场景:安全暴露内部成员或数组元素

最常用的就是让外部拿到某个字段的智能指针,但又不希望它影响整个对象的生存期决策。比如一个缓存容器持有 shared_ptr<vector>></vector>,用户只想持有一个 string& 的安全包装:

立即学习C++免费学习笔记(深入)”;

auto data = make_shared<vector<string>>(1000);
shared_ptr<string> first_str(data, &(*data)[0]); // 共享 data 的控制块

这时 first_str 可以放心传给其他模块,哪怕它被复制多次,只要 data 还活着,first_str.get() 就有效。

笔灵降AI
笔灵降AI

论文降AI神器,适配知网及维普!一键降至安全线,100%保留原文格式;无口语化问题,文风更学术,降后字数控制最佳!

下载
  • 不要用 shared_ptr<string>(new string(...))</string> —— 额外分配、脱离原容器生命周期
  • 不能用 shared_ptr<string>(&(*data)[0])</string> —— 控制块丢失,析构时 double-free 或 crash
  • 如果 vector 后续 resize,&(*data)[0] 地址可能失效,别名指针变成悬垂——这属于逻辑风险,别名构造本身不管这个

为什么不能用 static\_cast 或 get() 直接转?

static_cast<shared_ptr>>(sp)</shared_ptr> 编译不过(类型不匹配),shared_ptr<t>(sp.get())</t> 更危险:它会新建控制块,导致原始 sp 和新指针各自管理同一块内存,析构时必然 double-delete。

别名构造是唯一能「零开销复用控制块 + 改变所指类型」的机制。它的底层原理是把 ptr 存进已有的控制块,不碰 ref-count 内存布局,也不调用新的 deleter。

  • sp.get() 返回的是原始 U*,不能直接喂给 shared_ptr<t></t> 构造函数
  • dynamic_pointer_cast 是类型安全向下转型,但它要求多态和虚函数,且仍需原 shared_ptr 是基类指针
  • 别名构造不要求继承关系,TU 可以完全无关(比如 U=BufferT=char

容易踩的坑:别名指针比原 shared_ptr 死得早?

不会。别名构造出来的 shared_ptr 和原 shared_ptr 共享同一个控制块,所以只要还有一个别名或原实例活着,资源就不会释放。但反过来说:如果原 shared_ptr 已经析构,所有别名都变成空(.get() == nullptr),访问会段错误。

真正危险的是「误以为别名能延长原对象寿命」。例如:

shared_ptr<BigObj> get_obj() { return make_shared<BigObj>(); }
auto p = shared_ptr<int>(get_obj(), &get_obj()->field); // 错!两个临时 shared_ptr,第一个立刻销毁

这里 get_obj() 调用两次,第一次返回的 shared_ptr 在表达式结束就析构了,p 持有的是已释放对象的字段地址。

  • 必须确保传入的第一个参数是稳定存在的 shared_ptr 变量(非临时量、非右值)
  • 数组场景下,&arr[i] 合法,但 arr + i 也合法;而 arr.data() + i 更推荐,语义清晰
  • 如果目标是 const 子对象,别名构造出 shared_ptr<const t></const> 完全没问题,类型转换自动发生

别名构造不是语法糖,它是 C++ 智能指针里少有的、允许你精确控制“谁决定内存生死”和“谁决定接口形态”分离的机制。用错一次,调试成本远高于写两行注释。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

770

2023.08.02

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

199

2023.11.20

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

22

2025.11.27

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

547

2023.09.20

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

254

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

105

2025.10.23

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1508

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

423

2025.10.17

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

561

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9.7万人学习

C 教程
C 教程

共75课时 | 4.8万人学习

C++教程
C++教程

共115课时 | 18.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号