首页 > 后端开发 > C++ > 正文

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

P粉602998670
发布: 2025-07-07 08:01:02
原创
123人浏览过

智能指针是c++++中自动管理内存的工具,主要包括unique_ptr、shared_ptr和weak_ptr。1. unique_ptr用于独占所有权,不可复制,转移需用std::move,销毁时自动删除对象;2. shared_ptr允许多个指针共享同一对象,通过引用计数管理生命周期,但需注意循环引用问题;3. weak_ptr作为弱引用不增加引用计数,用于解决循环引用及实现缓存等场景。合理选择智能指针可避免内存泄漏并提升效率。

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

智能指针,说白了,就是帮你自动管理内存的指针。现代 C++ 里,它们已经是标配了,unique_ptr、shared_ptr 和 weak_ptr,各有各的用处和侧重点,用错了地方,轻则效率打折,重则内存泄漏。

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

unique_ptr、shared_ptr、weak_ptr 就像是内存管理战场上的三员大将,各有千秋,用对了地方才能发挥最大威力。

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

解决方案

首先,unique_ptr,顾名思义,它所指向的对象只能被一个 unique_ptr 拥有。这意味着,所有权是独占的,不能简单地复制。当 unique_ptr 销毁时,它所指向的对象也会被自动删除。这避免了忘记 delete 造成的内存泄漏。

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

#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass(int value) : value_(value) {
        std::cout << "MyClass constructed with value: " << value_ << std::endl;
    }
    ~MyClass() {
        std::cout << "MyClass destructed with value: " << value_ << std::endl;
    }

    int getValue() const { return value_; }

private:
    int value_;
};


int main() {
    // 创建一个 unique_ptr,指向一个 MyClass 对象
    std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>(10);
    std::cout << "Value: " << ptr1->getValue() << std::endl;

    // 尝试复制 unique_ptr 会导致编译错误
    // std::unique_ptr<MyClass> ptr2 = ptr1; // 错误:unique_ptr 不可复制

    // 可以使用 std::move 转移所有权
    std::unique_ptr<MyClass> ptr2 = std::move(ptr1);
    std::cout << "Value: " << ptr2->getValue() << std::endl;

    // 现在 ptr1 不再拥有对象,访问它会导致未定义行为
    // std::cout << "Value: " << ptr1->getValue() << std::endl; // 避免这样做

    // ptr2 在 main 函数结束时会被销毁,MyClass 对象也会被销毁
    return 0;
}
登录后复制

shared_ptr 则允许多个指针指向同一个对象,它使用引用计数来跟踪有多少个 shared_ptr 指向该对象。只有当引用计数降为零时,对象才会被删除。这使得在多个对象之间共享所有权变得非常方便。但是,循环引用会导致内存泄漏,需要小心。

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比
#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass(int value) : value_(value) {
        std::cout << "MyClass constructed with value: " << value_ << std::endl;
    }
    ~MyClass() {
        std::cout << "MyClass destructed with value: " << value_ << std::endl;
    }

    int getValue() const { return value_; }

private:
    int value_;
};

int main() {
    // 创建一个 shared_ptr,指向一个 MyClass 对象
    std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>(20);
    std::cout << "Value: " << ptr1->getValue() << std::endl;
    std::cout << "Reference count: " << ptr1.use_count() << std::endl;

    // 复制 shared_ptr,引用计数增加
    std::shared_ptr<MyClass> ptr2 = ptr1;
    std::cout << "Value: " << ptr2->getValue() << std::endl;
    std::cout << "Reference count: " << ptr1.use_count() << std::endl;
    std::cout << "Reference count: " << ptr2.use_count() << std::endl;

    // ptr1 和 ptr2 都指向同一个对象,该对象在 main 函数结束时会被销毁一次
    return 0;
}
登录后复制

最后,weak_ptr 是一种“弱引用”,它指向由 shared_ptr 管理的对象,但不增加引用计数。weak_ptr 可以用来观察对象是否仍然存在,而不会阻止对象被删除。这对于解决循环引用问题非常有用。

#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass(int value) : value_(value) {
        std::cout << "MyClass constructed with value: " << value_ << std::endl;
    }
    ~MyClass() {
        std::cout << "MyClass destructed with value: " << value_ << std::endl;
    }

    int getValue() const { return value_; }

private:
    int value_;
};

int main() {
    // 创建一个 shared_ptr,指向一个 MyClass 对象
    std::shared_ptr<MyClass> sharedPtr = std::make_shared<MyClass>(30);
    std::cout << "Shared pointer value: " << sharedPtr->getValue() << std::endl;
    std::cout << "Shared pointer reference count: " << sharedPtr.use_count() << std::endl;

    // 创建一个 weak_ptr,指向同一个 MyClass 对象
    std::weak_ptr<MyClass> weakPtr = sharedPtr;
    std::cout << "Weak pointer expired: " << weakPtr.expired() << std::endl;

    // 可以使用 weak_ptr 的 lock() 方法获取一个 shared_ptr
    std::shared_ptr<MyClass> lockedPtr = weakPtr.lock();
    if (lockedPtr) {
        std::cout << "Locked pointer value: " << lockedPtr->getValue() << std::endl;
        std::cout << "Shared pointer reference count: " << sharedPtr.use_count() << std::endl;
    } else {
        std::cout << "Weak pointer is expired." << std::endl;
    }

    // 释放 shared_ptr
    sharedPtr.reset();
    std::cout << "Shared pointer reference count: " << sharedPtr.use_count() << std::endl;
    std::cout << "Weak pointer expired: " << weakPtr.expired() << std::endl;

    // 再次尝试使用 weak_ptr 的 lock() 方法
    lockedPtr = weakPtr.lock();
    if (lockedPtr) {
        std::cout << "Locked pointer value: " << lockedPtr->getValue() << std::endl;
    } else {
        std::cout << "Weak pointer is expired." << std::endl;
    }

    return 0;
}
登录后复制

何时使用 unique_ptr?

当你希望对象的所有权是唯一的,并且在 unique_ptr 销毁时自动删除对象时,使用 unique_ptr。例如,在工厂函数中返回新创建的对象,或者在类中拥有一个独占的资源。

shared_ptr 如何避免循环引用导致的内存泄漏?

循环引用是指两个或多个对象互相持有 shared_ptr,导致引用计数永远不为零,对象永远无法被删除。解决循环引用的方法是使用 weak_ptr。一个对象持有另一个对象的 weak_ptr,而不是 shared_ptr,这样就不会增加引用计数。当需要访问对象时,可以使用 weak_ptr::lock() 方法获取一个 shared_ptr,如果对象已经被删除,lock() 方法会返回 nullptr。

weak_ptr 的使用场景有哪些?

除了解决循环引用问题,weak_ptr 还可以用于缓存。例如,一个缓存对象可以使用 weak_ptr 来持有缓存项,当缓存项不再被其他对象使用时,缓存对象会自动释放缓存项。还可以用于观察者模式,观察者可以使用 weak_ptr 来持有被观察者的引用,当被观察者被删除时,观察者可以自动取消订阅。

以上就是现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

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