C++中智能指针怎么用?智能指针使用与原理分析

来源:前端技术作者:又改需求头衔:程序员
导读:本期聚焦于小伙伴创作的《C++中智能指针怎么用?智能指针使用与原理分析》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++中智能指针怎么用?智能指针使用与原理分析》有用,将其分享出去将是对创作者最好的鼓励。

C++的智能指针是标准库提供的用于动态内存管理的模板类,能够自动释放所指向的堆内存,避免手动调用delete带来的内存泄漏、重复释放等问题。目前标准库主要提供了shared_ptr、unique_ptr、weak_ptr三种智能指针,各自有不同的适用场景和特性。

C++中智能指针怎么用?智能指针使用与原理分析

常用智能指针的使用方法

unique_ptr:独占所有权的智能指针

unique_ptr是独占型智能指针,同一时间只能有一个unique_ptr指向同一块堆内存,无法通过拷贝构造或拷贝赋值转移所有权,只能通过移动语义转移。

基本使用示例如下:

#include <memory>
#include <iostream>

class Test {
public:
    Test() { std::cout << "Test构造" << std::endl; }
    ~Test() { std::cout << "Test析构" << std::endl; }
    void print() { std::cout << "Test print" << std::endl; }
};

int main() {
    // 初始化unique_ptr
    std::unique_ptr<Test> ptr1(new Test());
    // 调用指向对象的方法
    ptr1->print();
    // 转移所有权,转移后ptr1变为空
    std::unique_ptr<Test> ptr2 = std::move(ptr1);
    if (!ptr1) {
        std::cout << "ptr1已为空" << std::endl;
    }
    // ptr2离开作用域时自动释放内存
    return 0;
}

shared_ptr:共享所有权的智能指针

shared_ptr是共享型智能指针,多个shared_ptr可以指向同一块堆内存,内部通过引用计数记录指向该内存的智能指针数量,当引用计数为0时自动释放内存。

使用示例如下:

#include <memory>
#include <iostream>

class Test {
public:
    Test() { std::cout << "Test构造" << std::endl; }
    ~Test() { std::cout << "Test析构" << std::endl; }
};

int main() {
    // 初始化shared_ptr
    std::shared_ptr<Test> ptr1(new Test());
    {
        // 拷贝构造,引用计数加1
        std::shared_ptr<Test> ptr2 = ptr1;
        std::cout << "当前引用计数:" << ptr1.use_count() << std::endl;
    }
    // ptr2离开作用域,引用计数减1
    std::cout << "当前引用计数:" << ptr1.use_count() << std::endl;
    return 0;
}

weak_ptr:弱引用智能指针

weak_ptr是弱引用智能指针,它指向shared_ptr管理的对象,但不会增加引用计数,主要用于解决shared_ptr的循环引用问题。

使用示例如下:

#include <memory>
#include <iostream>

class B;
class A {
public:
    std::shared_ptr<B> b_ptr;
    ~A() { std::cout << "A析构" << std::endl; }
};

class B {
public:
    std::weak_ptr<A> a_ptr; // 使用weak_ptr避免循环引用
    ~B() { std::cout << "B析构" << std::endl; }
};

int main() {
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();
    a->b_ptr = b;
    b->a_ptr = a;
    // 离开作用域后A和B都能正常析构
    return 0;
}

智能指针的底层实现原理

unique_ptr的实现逻辑

unique_ptr的核心是通过删除拷贝构造和拷贝赋值函数,只允许移动构造和移动赋值,同时内部封装了原始指针,在析构函数中调用delete释放内存。简化实现示例如下:

template <typename T>
class MyUniquePtr {
private:
    T* ptr;
public:
    // 构造函数
    explicit MyUniquePtr(T* p = nullptr) : ptr(p) {}
    // 禁止拷贝构造
    MyUniquePtr(const MyUniquePtr&) = delete;
    // 禁止拷贝赋值
    MyUniquePtr& operator=(const MyUniquePtr&) = delete;
    // 移动构造
    MyUniquePtr(MyUniquePtr&& other) noexcept : ptr(other.ptr) {
        other.ptr = nullptr;
    }
    // 移动赋值
    MyUniquePtr& operator=(MyUniquePtr&& other) noexcept {
        if (this != &other) {
            delete ptr;
            ptr = other.ptr;
            other.ptr = nullptr;
        }
        return *this;
    }
    // 析构函数
    ~MyUniquePtr() {
        delete ptr;
    }
    // 重载箭头运算符
    T* operator->() const { return ptr; }
    // 重载解引用运算符
    T& operator*() const { return *ptr; }
    // 判断是否为空
    operator bool() const { return ptr != nullptr; }
};

shared_ptr的实现逻辑

shared_ptr内部除了保存指向对象的原始指针,还会维护一个指向引用计数对象的指针,引用计数对象记录了当前指向该资源的shared_ptr数量和控制块信息。简化实现示例如下:

template <typename T>
class MySharedPtr {
private:
    T* ptr;
    int* count; // 引用计数
public:
    // 构造函数
    explicit MySharedPtr(T* p = nullptr) : ptr(p), count(nullptr) {
        if (ptr) {
            count = new int(1);
        }
    }
    // 拷贝构造,引用计数加1
    MySharedPtr(const MySharedPtr& other) : ptr(other.ptr), count(other.count) {
        if (count) {
            (*count)++;
        }
    }
    // 拷贝赋值
    MySharedPtr& operator=(const MySharedPtr& other) {
        if (this != &other) {
            // 先处理当前对象的引用计数
            if (count && --(*count) == 0) {
                delete ptr;
                delete count;
            }
            // 赋值新对象的信息
            ptr = other.ptr;
            count = other.count;
            if (count) {
                (*count)++;
            }
        }
        return *this;
    }
    // 析构函数
    ~MySharedPtr() {
        if (count && --(*count) == 0) {
            delete ptr;
            delete count;
        }
    }
    // 获取引用计数
    int use_count() const {
        return count ? *count : 0;
    }
    // 重载箭头运算符
    T* operator->() const { return ptr; }
    // 重载解引用运算符
    T& operator*() const { return *ptr; }
};

智能指针使用注意事项

  • 不要将原始指针和智能指针混合使用,避免同一块内存被多次释放
  • 不要用同一个原始指针初始化多个shared_ptr,会导致引用计数错误
  • 优先使用make_shared和make_unique初始化智能指针,比直接new更安全,效率更高
  • 避免shared_ptr的循环引用,出现循环引用场景时使用weak_ptr打破循环
  • unique_ptr作为函数返回值不需要显式调用std::move,编译器会自动优化为移动构造

三种智能指针的对比

智能指针类型所有权特性引用计数适用场景
unique_ptr独占所有权明确资源只会被一个所有者持有,不需要共享的场景
shared_ptr共享所有权资源需要被多个所有者共同使用的场景
weak_ptr弱引用不增加计数解决shared_ptr循环引用,或者需要临时访问shared_ptr资源但不想影响生命周期的场景

C++智能指针shared_ptrunique_ptrweak_ptr修改时间:2026-07-04 07:27:36

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。