您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > C/C++/C#

C++ 智能指针 unique_ptr

时间:2023-04-08 16:29:09  来源:今日头条  作者:睿智的海边风浪

C++11 中新增了一种智能指针类型 unique_ptr,它是一种独占式的智能指针,用于管理动态分配的对象,并确保在其生命周期结束时正确释放资源。在使用 unique_ptr 时,指针指向的资源只能被一个 unique_ptr 持有,当 unique_ptr 被销毁时,它所指向的对象也被自动释放。

unique_ptr 的设计思想是“资源所有权的独占”,因此它的构造和析构函数都被设计为模板函数,可以自动地匹配任意类型的对象。与 shared_ptr 不同,unique_ptr 不需要维护引用计数,因此它的内存开销更小,性能更高。

unique_ptr 的使用方式与原始指针类似,可以通过重载运算符 * 和 -> 来访问指向的对象,也可以使用 get() 函数来获取指向的原始指针。与 shared_ptr 类似,unique_ptr 也可以通过移动语义来转移所有权,即将一个 unique_ptr 赋值给另一个 unique_ptr 时,被赋值的 unique_ptr 所指向的对象会转移所有权给新的 unique_ptr,被赋值的 unique_ptr 变为 null。

下面是一个示例程序,演示了 unique_ptr 的基本用法:

#include <IOStream>
#include <memory>

class MyClass {
public:
    MyClass() {
        std::cout << "MyClass constructor" << std::endl;
    }
    ~MyClass() {
        std::cout << "MyClass destructor" << std::endl;
    }
    void hello() {
        std::cout << "Hello, unique_ptr!" << std::endl;
    }
};

int mAIn() {
    std::unique_ptr<MyClass> ptr(new MyClass); // 构造 unique_ptr,指向动态分配的 MyClass 对象
    ptr->hello(); // 使用 -> 运算符访问 MyClass 对象的成员函数
    (*ptr).hello(); // 使用 * 运算符访问 MyClass 对象的成员函数
    std::unique_ptr<MyClass> ptr2(std::move(ptr)); // 将 ptr 的所有权转移给 ptr2
    if (!ptr) {
        std::cout << "ptr is null" << std::endl;
    }
    ptr2->hello();
    return 0;
}

当 unique_ptr 被销毁时,它所指向的对象也被自动销毁。在示例程序中,第一个 unique_ptr 的所有权被转移给第二个 unique_ptr,因此第一个 unique_ptr 变为 null。当第二个 unique_ptr 被销毁时,它所指向的 MyClass 对象也被自动销毁。

std::unique_ptr 有以下几个重要的成员函数:

  • get(): 返回指向被管理对象的原始指针。
  • release(): 释放指针所有权,并返回指向被管理对象的原始指针。
  • reset(): 释放指针,并重新指向一个新对象,或者为空指针。
  • operator bool(): 返回 unique_ptr 是否持有对象的布尔值。
  1. 创建一个 unique_ptr:
    创建一个 std::unique_ptr 对象需要使用 std::make_unique 或者使用 new 操作符。和 std::shared_ptr 一样,std::make_unique 是更好的选择,因为它能够防止内存泄漏,代码更加简洁明了。
// 使用 std::make_unique 创建 unique_ptr 对象
std::unique_ptr<int> p1 = std::make_unique<int>(10);
// 使用 new 创建 unique_ptr 对象
std::unique_ptr<int> p2(new int(20));
  1. 释放 unique_ptr 的内存
    释放 std::unique_ptr 的内存有两种方式:
  • 使用 std::unique_ptr 的 reset() 函数,将 std::unique_ptr 对象的指针设置为 nullptr,释放原来指向的内存。
std::unique_ptr<int> p(new int(30));
p.reset(); // 将 p 的指针设置为 nullptr,释放原来指向的内存
  • std::unique_ptr 对象在生命周期结束时会自动释放其所占用的内存。在 unique_ptr 对象超出作用域或被显式删除时,它所占用的内存将被自动释放。
{
    std::unique_ptr<int> p(new int(40));
    // unique_ptr 对象超出作用域,内存自动释放
}
  1. 将 unique_ptr 对象转移给其他 unique_ptr 对象
    使用 std::move() 函数可以将一个 std::unique_ptr 对象转移给另一个 std::unique_ptr 对象。被转移的 std::unique_ptr 对象将失去对其所指向的内存的所有权,并被置为 nullptr。
std::unique_ptr<int> p1(new int(50));
std::unique_ptr<int> p2(std::move(p1)); // 将 p1 对象转移给 p2 对象
  1. 获取 unique_ptr 对象的指针
    可以使用 std::unique_ptr 对象的 get() 函数获取其所指向的内存的指针。
std::unique_ptr<int> p(new int(60));
int* p_int = p.get(); // 获取 p 对象所指向的内存的指针

需要注意的是,get() 函数返回的是裸指针,不具有 unique_ptr 对象的智能指针功能。因此在使用 get() 函数返回的裸指针时需要注意内存管理的问题。

除了以上几点之外,还应该注意以下几点:

  • 不要使用 unique_ptr 对象的裸指针,除非你要传递给接收裸指针参数的函数。在这种情况下,应该显式地将 unique_ptr 对象释放资源,并确保不再访问这些资源。可以使用 get 方法获取 unique_ptr 对象内部的裸指针。
  • 不要将相同的内存资源分配给多个 unique_ptr 对象,这可能会导致重复释放同一块内存。
  • 不要将 unique_ptr 对象的所有权传递给另一个 unique_ptr 对象,因为 unique_ptr 不能被复制。如果需要将所有权传递给另一个对象,可以考虑使用 std::move 或者使用 std::shared_ptr


Tags:C++   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
C++中的外部模板及其在当前编译文件中的实例化
在C++中,模板是一种泛型编程的工具,它允许程序员以一种类型无关的方式编写代码。然而,模板的一个常见问题是它们会导致编译时间增加,特别是在大型项目中,当多个源文件包含相同的...【详细内容】
2024-04-11  Search: C++  点击:(2)  评论:(0)  加入收藏
C++常见避坑指南
C++ 从入门到放弃?本文主要总结了在C++开发或review过程中常见易出错点做了归纳总结,希望借此能增进大家对C++的了解,减少编程出错,提升工作效率,也可以作为C++开发的避坑攻略。...【详细内容】
2024-04-03  Search: C++  点击:(5)  评论:(0)  加入收藏
C++ 之父反驳白宫警告:自诞生第一天起,C++ 的目标就一直是提高安全性
整理 | 郑丽媛上个月,美国白宫国家网络主任办公室(ONCD)在一份主题为《回到基础构件:通往安全软件之路》的 19 页 PDF 报告中,呼吁开发人员停止使用容易出现内存安全漏洞的编程语...【详细内容】
2024-03-25  Search: C++  点击:(4)  评论:(0)  加入收藏
八个 C++ 开源项目,帮助初学者进阶成长
通过参与或阅读开源项目的源代码,你可以获得丰富的实践机会。实际的项目代码比简单的教程更具挑战性,可以帮助你深入理解 C++ 的各种概念和技术。1.ThreadPool一个简单的 C++1...【详细内容】
2024-03-22  Search: C++  点击:(21)  评论:(0)  加入收藏
C++多线程编程:解锁性能与并发的奥秘
今天我们将深入探讨C++中的多线程编程,揭示多线程如何解锁性能潜力,提高程序的并发性能。什么是多线程?在计算机科学中,多线程是指一个进程(程序的执行实例)中的多个线程同时执行...【详细内容】
2024-02-03  Search: C++  点击:(69)  评论:(0)  加入收藏
C++代码优化攻略
今天我们将深入探讨C++性能优化的世界。在当今软件开发的浪潮中,高性能的代码是必不可少的。无论是开发桌面应用、移动应用,还是嵌入式系统,性能都是关键。1. 选择合适的数据结...【详细内容】
2024-01-26  Search: C++  点击:(115)  评论:(0)  加入收藏
C++质数检测器的设计与实现​
质数,作为数学中的一个基本概念,一直以其独特的性质吸引着众多研究者和爱好者。质数是指大于1的自然数中,除了1和它本身以外不再有其他因数的数。在实际应用中,质数检测也扮演着...【详细内容】
2024-01-15  Search: C++  点击:(115)  评论:(0)  加入收藏
指针变量在C/C++中的内存占用
在编程领域,尤其是C和C++这类底层语言中,指针是一个核心概念,它允许程序直接操作内存地址。然而,关于指针本身在内存中占用的空间大小,却常常让初学者感到困惑。本文将深入探讨这...【详细内容】
2024-01-09  Search: C++  点击:(95)  评论:(0)  加入收藏
C++的面向对象编程:深入解析与理解
当我们谈论C++时,面向对象编程(OOP)是一个无法回避的话题。那么,C++的面向对象究竟是什么?为什么它如此重要?本文将从基本概念到实际应用,为您详细解析C++中的面向对象编程。一、面...【详细内容】
2024-01-03  Search: C++  点击:(97)  评论:(0)  加入收藏
有什么好用的C/C++源代码混淆工具?
开始使用ipaguard前言iOS加固保护是直接针对ios ipa二进制文件的保护技术,可以对iOS APP中的可执行文件进行深度混淆、加密。使用任何工具都无法逆向、破解还原源文件。对APP...【详细内容】
2023-12-29  Search: C++  点击:(119)  评论:(0)  加入收藏
▌简易百科推荐
C++中的外部模板及其在当前编译文件中的实例化
在C++中,模板是一种泛型编程的工具,它允许程序员以一种类型无关的方式编写代码。然而,模板的一个常见问题是它们会导致编译时间增加,特别是在大型项目中,当多个源文件包含相同的...【详细内容】
2024-04-11  鲨鱼编程  微信公众号  Tags:C++   点击:(2)  评论:(0)  加入收藏
C++常见避坑指南
C++ 从入门到放弃?本文主要总结了在C++开发或review过程中常见易出错点做了归纳总结,希望借此能增进大家对C++的了解,减少编程出错,提升工作效率,也可以作为C++开发的避坑攻略。...【详细内容】
2024-04-03  腾讯技术工程    Tags:C++   点击:(5)  评论:(0)  加入收藏
C++ 之父反驳白宫警告:自诞生第一天起,C++ 的目标就一直是提高安全性
整理 | 郑丽媛上个月,美国白宫国家网络主任办公室(ONCD)在一份主题为《回到基础构件:通往安全软件之路》的 19 页 PDF 报告中,呼吁开发人员停止使用容易出现内存安全漏洞的编程语...【详细内容】
2024-03-25    CSDN  Tags:C++   点击:(4)  评论:(0)  加入收藏
八个 C++ 开源项目,帮助初学者进阶成长
通过参与或阅读开源项目的源代码,你可以获得丰富的实践机会。实际的项目代码比简单的教程更具挑战性,可以帮助你深入理解 C++ 的各种概念和技术。1.ThreadPool一个简单的 C++1...【详细内容】
2024-03-22  AI让生活更美好  微信公众号  Tags:C++   点击:(21)  评论:(0)  加入收藏
C# 中15个值得收藏的开源项目推荐
在开源的世界里,C# 编程语言也占有一席之地。这些开源项目涵盖了多个领域,从框架、库到工具,它们为C#开发者提供了丰富的资源和工具,帮助他们更高效地开发、测试和部署应用程序...【详细内容】
2024-03-20  程序员编程日记  微信公众号  Tags:C#   点击:(30)  评论:(0)  加入收藏
C#异步编程:Task.Run vs. async-await,掌握基础与高级用法
概述:C#中的异步编程有两主要方式:Task.Run用于在后台线程执行同步操作,而async-await更适用于清晰表达异步流程。基础用法展示了它们的简单应用,高级用法则演示了它们的结合使...【详细内容】
2024-03-09  架构师老卢  今日头条  Tags:C#   点击:(23)  评论:(0)  加入收藏
C++多线程编程:解锁性能与并发的奥秘
今天我们将深入探讨C++中的多线程编程,揭示多线程如何解锁性能潜力,提高程序的并发性能。什么是多线程?在计算机科学中,多线程是指一个进程(程序的执行实例)中的多个线程同时执行...【详细内容】
2024-02-03     AI让生活更美好  Tags:C++   点击:(69)  评论:(0)  加入收藏
C++代码优化攻略
今天我们将深入探讨C++性能优化的世界。在当今软件开发的浪潮中,高性能的代码是必不可少的。无论是开发桌面应用、移动应用,还是嵌入式系统,性能都是关键。1. 选择合适的数据结...【详细内容】
2024-01-26  AI让生活更美好  微信公众号  Tags:C++   点击:(115)  评论:(0)  加入收藏
C# 线程本地存储为什么线程间值不一样
为什么用 ThreadStatic 标记的字段,只有第一个线程拿到了初始值,其他线程都是默认值,让我能不能帮他解答一下,尼玛,我也不是神仙什么都懂,既然问了,那我试着帮他解答一下,也给后面类...【详细内容】
2024-01-26  一线码农聊技术  微信公众号  Tags:C#   点击:(68)  评论:(0)  加入收藏
C++质数检测器的设计与实现​
质数,作为数学中的一个基本概念,一直以其独特的性质吸引着众多研究者和爱好者。质数是指大于1的自然数中,除了1和它本身以外不再有其他因数的数。在实际应用中,质数检测也扮演着...【详细内容】
2024-01-15  鲨鱼编程  微信公众号  Tags:C++   点击:(115)  评论:(0)  加入收藏
站内最新
站内热门
站内头条