C++智能指针在类成员中的应用有哪些技巧和注意事项

来源:AI大模型作者:日本程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《C++智能指针在类成员中的应用有哪些技巧和注意事项》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++智能指针在类成员中的应用有哪些技巧和注意事项》有用,将其分享出去将是对创作者最好的鼓励。

在C++的类设计中,成员变量的内存管理一直是需要重点关注的环节,传统的使用裸指针作为类成员的方式,需要开发者手动控制内存的分配和释放,很容易因为遗漏释放或者重复释放导致程序出现内存相关问题。智能指针的出现很好地解决了这类问题,它可以通过自身的生命周期管理所指向的对象,自动在合适的时机释放内存。不同的智能指针类型特性不同,在类成员场景下的适用场景也有明显区别,需要根据实际需求合理选择。

C++智能指针在类成员中的应用有哪些技巧和注意事项

unique_ptr作为类成员的应用

unique_ptr是独占所有权的智能指针,同一时间只能有一个unique_ptr指向对应的对象,适合用来管理类独占的资源成员。当类对象被销毁时,unique_ptr会自动释放所指向的对象,不需要手动处理。

基本使用示例

下面是一个使用unique_ptr作为类成员的简单示例,类Resource是需要被管理的资源类,Owner类通过unique_ptr持有Resource的实例:

#include <memory>
#include <iostream>

// 资源类
class Resource {
public:
    Resource() {
        std::cout << "Resource 构造" << std::endl;
    }
    ~Resource() {
        std::cout << "Resource 析构" << std::endl;
    }
    void do_something() {
        std::cout << "Resource 执行操作" << std::endl;
    }
};

// 持有资源的类
class Owner {
private:
    // 独占所有权的智能指针成员
    std::unique_ptr<Resource> res_ptr;
public:
    // 构造函数中初始化智能指针
    Owner() : res_ptr(std::make_unique<Resource>()) {}
    
    // 提供访问资源的方法
    void use_resource() {
        if (res_ptr) {
            res_ptr->do_something();
        }
    }
    
    // 禁止拷贝构造和拷贝赋值,因为unique_ptr不可拷贝
    Owner(const Owner&) = delete;
    Owner& operator=(const Owner&) = delete;
    
    // 允许移动构造和移动赋值
    Owner(Owner&&) = default;
    Owner& operator=(Owner&&) = default;
};

int main() {
    Owner owner;
    owner.use_resource();
    // owner离开作用域时,res_ptr自动释放Resource对象
    return 0;
}

使用注意事项

  • unique_ptr不可拷贝,所以如果类包含unique_ptr成员,默认情况下类的拷贝构造和拷贝赋值会被删除,需要显式定义或者声明为删除,避免误用。
  • 优先使用std::make_unique来创建unique_ptr,它比直接使用new更安全,能避免一些潜在的内存泄漏问题。
  • 如果需要在类之间转移资源的所有权,可以使用移动语义,将unique_ptr的所有权转移给其他对象。

shared_ptr作为类成员的应用

shared_ptr是共享所有权的智能指针,多个shared_ptr可以指向同一个对象,通过引用计数管理对象的生命周期,当最后一个指向对象的shared_ptr被销毁时,对象才会被释放。适合多个类需要共享同一个资源成员的场景。

基本使用示例

下面的示例中,多个Viewer类的实例可以共享同一个Resource对象:

#include <memory>
#include <iostream>
#include <vector>

class Resource {
public:
    Resource() {
        std::cout << "Resource 构造" << std::endl;
    }
    ~Resource() {
        std::cout << "Resource 析构" << std::endl;
    }
    void do_something() {
        std::cout << "Resource 执行操作" << std::endl;
    }
};

// 共享资源的查看者类
class Viewer {
private:
    std::shared_ptr<Resource> res_ptr;
public:
    Viewer(std::shared_ptr<Resource> ptr) : res_ptr(ptr) {}
    
    void use_resource() {
        if (res_ptr) {
            res_ptr->do_something();
        }
    }
};

int main() {
    // 创建共享的资源
    auto shared_res = std::make_shared<Resource>();
    std::cout << "资源引用计数: " << shared_res.use_count() << std::endl;
    
    // 创建多个Viewer共享资源
    Viewer v1(shared_res);
    std::cout << "资源引用计数: " << shared_res.use_count() << std::endl;
    
    Viewer v2(shared_res);
    std::cout << "资源引用计数: " << shared_res.use_count() << std::endl;
    
    // 离开作用域时,引用计数逐步减少,最后资源被释放
    return 0;
}

循环引用问题

使用shared_ptr作为类成员时,最容易遇到的问题是循环引用,即两个类的成员互相用shared_ptr指向对方,导致引用计数永远无法降为0,引发内存泄漏。示例代码如下:

#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::shared_ptr<A> a_ptr;
    ~B() {
        std::cout << "B 析构" << std::endl;
    }
};

int main() {
    auto a = std::make_shared<A>();
    auto b = std::make_shared<B>();
    a->b_ptr = b;
    b->a_ptr = a;
    // 此时a和b的引用计数都是2,离开作用域后引用计数降为1,不会触发析构,造成内存泄漏
    return 0;
}

解决循环引用的方式是,将其中一个类的成员改为weak_ptrweak_ptr不会增加引用计数,只是弱引用指向的对象,需要时可以通过lock()方法获取shared_ptr访问对象。修改后的B类如下:

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

智能指针作为类成员的选型建议

智能指针类型适用场景注意事项
unique_ptr类独占资源,不需要和其他对象共享类默认拷贝功能会被删除,需要手动处理拷贝逻辑
shared_ptr多个对象需要共享同一个资源注意避免循环引用,必要时搭配weak_ptr使用
weak_ptr作为辅助成员,避免循环引用,或者临时引用资源访问资源前需要调用lock()检查资源是否还存在

常见问题总结

  • 不要在类的析构函数中手动释放智能指针指向的对象,智能指针会自动管理生命周期,手动释放会导致重复释放的问题。
  • 避免将this指针直接交给智能指针管理,除非类继承自std::enable_shared_from_this,否则会导致多个独立的控制块,引发错误释放。
  • 如果类成员是智能指针,初始化时尽量在构造函数的初始化列表中完成,避免在构造函数体内赋值,减少不必要的临时对象。

C++智能指针类成员shared_ptrunique_ptr修改时间:2026-06-16 15:00:29

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