南京苏嵌教育

C++新特性 智能指针std::unique_ptr

发布日期:2024年12月26日

点赞、收藏、星标不会错过精彩推送哦!当我们在编写 C++ ...

点赞、收藏、星标不会错过精彩推送哦!当我们在编写 C++ 代码时,动态分配内存是一个常见的需求。然而,手动管理内存往往会导致内存泄漏、悬挂指针以及难以维护的代码。为了解决这些问题,C++11 引入了智能指针,其中之一就是 std::unique_ptr。std::unique_ptr 是一个智能指针类,用于管理动态分配的对象,并确保在其生命周期结束时释放相应的内存。在这篇文章中,我们将深入了解 std::unique_ptr 的用法、优点以及一些注意事项。1. 简介std::unique_ptr 是 C++ 标准库中的模板类,位于 <memory> 头文件中。它的特点是在同一时间只能有一个 unique_ptr 指向给定的对象,因此它是一种独占所有权的智能指针。当 unique_ptr 被销毁时,它所管理的内存也会被自动释放,从而避免了内存泄漏的风险。2. 基本用法下面是 std::unique_ptr 的基本用法示例:#include <iostream>#include <memory>int main() {    // 创建一个 unique_ptr,指向一个 int 对象    std::unique_ptr<int> ptr(new int(42));    // 使用 unique_ptr 操作指向的对象    std::cout << "Value: " << *ptr << std::endl;    // unique_ptr 在生命周期结束时会自动释放内存    return 0;}3. 构造函数std::unique_ptr 提供了多种构造函数,用于管理动态分配的资源,并在适当的时候释放这些资源。以下是 std::unique_ptr 的主要构造函数:默认构造函数:std::unique_ptr<T> ptr;创建一个空的 std::unique_ptr,不管理任何对象。指针构造函数:std::unique_ptr<T> ptr(new T);创建一个 std::unique_ptr,管理一个通过 new 运算符分配的对象。自定义删除器构造函数:有时候我们需要在释放内存之前执行一些特定的操作,这时可以使用自定义删除器。删除器是一个函数对象,负责在 unique_ptr 被销毁时调用,从而执行所需的操作。创建一个 std::unique_ptr,并指定一个自定义的删除器 customDeleter,用于释放资源。void customDeleter(int* ptr) {    std::cout << "Deleting memory at address: " << ptr << std::endl;    delete ptr;}int main() {    std::unique_ptr<int, decltype(&customDeleter)> ptr(new int(42), customDeleter);    return 0;}移动构造函数:std::unique_ptr<T> ptr1 = std::make_unique<T>(args);std::unique_ptr<T> ptr2 = std::move(ptr1);使用 std::move() 将 ptr1 的所有权转移到 ptr2。也可以使用 std::make_unique 创建对象,并将其移动到 std::unique_ptr。初始化列表构造函数(C++14 及以上版本):std::unique_ptr<T> ptr = std::make_unique<T>(args);使用 std::make_unique 创建对象,并将其初始化为 std::unique_ptr。4. 赋值操作std::unique_ptr 禁用了复制构造函数和赋值运算符,这是因为它的设计目标是提供独占所有权语义,这与赋值语义冲突。这意味着每个 std::unique_ptr 实例都是的,不能与其他 std::unique_ptr 实例共享所有权。禁用复制构造函数和赋值运算符有几个重要的原因:防止拷贝和悬空指针:如果允许复制构造函数和赋值运算符,那么可能会导致多个 std::unique_ptr 实例共享同一块内存,这可能会导致悬空指针问题。当一个 std::unique_ptr 被销毁时,它将尝试删除其所管理的对象,而其他共享同一对象的 std::unique_ptr 实例将指向已经被销毁的对象,这可能导致未定义的行为。强调独占所有权语义:std::unique_ptr 的设计目标之一是强调独占所有权语义,这意味着每个 std::unique_ptr 实例都应该是对象的所有者。通过禁用复制构造函数和赋值运算符,可以明确表明 std::unique_ptr 的性,从而更好地传达其设计意图。提高效率:禁用复制构造函数和赋值运算符可以防止不必要的对象拷贝,从而提高代码的效率。由于 std::unique_ptr 的目标是独占所有权,因此在大多数情况下,复制或赋值操作都不是必需的。要在 std::unique_ptr 之间转移所有权,可以使用 std::move() 函数。这样可以明确地指示所有权的转移,并避免悬空指针和未定义行为。5. 移动语义std::unique_ptr 支持移动语义,因此可以通过移动而不是拷贝来传递所有权。这意味着你可以将所有权从一个 unique_ptr 转移到另一个 unique_ptr,而不会触发额外的内存分配或释放。这在函数返回值和容器中的使用非常方便。std::unique_ptr<int> createIntPtr() {    return std::make_unique<int>(42);}int main() {    std::unique_ptr<int> ptr1 = createIntPtr(); // 移动语义    std::unique_ptr<int> ptr2 = std::move(ptr1); // 移动语义    return 0;}6. 注意事项不要使用裸指针初始化多个 unique_ptr,否则会导致多次释放同一块内存。避免循环引用,因为 unique_ptr 不能共享所有权。尽量使用 std::make_unique 来创建 unique_ptr,以避免不必要的内存分配。结论std::unique_ptr 是 C++ 中用于管理动态内存分配的一种安全、高效的方法。它通过独占所有权和移动语义来确保内存的正确释放,从而避免了内存泄漏和悬挂指针等问题。然而,在使用时仍需谨慎,避免一些常见的陷阱,以确保代码的正确性和健壮性。endLinux 世界 关注,回复【1024】海量Linux资料赠送精彩文章合集专辑推荐?【专辑】Linux命令与系统?【专辑】shell编程推荐阅读  点击标题可跳转1、Unix从兴盛到衰落鲜为人知的故事2、*受初学者欢迎的Linux系统ubuntu科普3、ubuntu 20.04 界面美化,提高工作舒适度!

Linux 世界我们专注于编程知识和软件设计分享,包括但不限于C/C++、linux开发。偶尔也聊聊程序人生。长按二维码,关注我们免责声明:整理文章为传播相关技术,版权归原作者所有,如有侵权,请联系删除。

加微信咨询
徐老师 @南京苏嵌教育
微信号:151******60

专业解答各类课程问题、介绍师资和学校情况

微信咨询
相关资讯
人工智能渗透进2024年高考作文 被大厂裁员后的4个月,我是怎么过来的(裁员故事) 常用的软件生命周期模型 操作系统体系结构:宏内核vs微内核 CentOS 停更!正式退出历史舞台
相关课程