C++ 智能指针详解

目录

1. std::unique_ptr

特点

示例

2. std::shared_ptr

特点

示例

3. std::weak_ptr

特点

示例

比较与选择

使用建议

总结


在C++中,智能指针(Smart Pointers)是用于管理动态分配内存的类模板,旨在帮助开发者避免内存泄漏和悬空指针等问题。C++标准库提供了三种主要的智能指针类型:std::unique_ptrstd::shared_ptrstd::weak_ptr。下面我们将详细介绍每种智能指针的特点及其使用场景。

1. std::unique_ptr

std::unique_ptr 是一种独占所有权的智能指针,意味着同一时间只能有一个 std::unique_ptr 指向某个对象。当 std::unique_ptr 被销毁或重新赋值时,它所管理的对象也会被自动销毁。

特点
  • 独占所有权:不允许复制,但可以通过移动语义转移所有权。
  • 自动释放资源:当 std::unique_ptr 离开作用域或被显式删除时,会自动调用析构函数释放资源。
示例
#include <iostream>
#include <memory>

int main() {
    // 创建一个 unique_ptr
    std::unique_ptr<int> uptr = std::make_unique<int>(10);

    // 访问指针指向的数据
    std::cout << "Value: " << *uptr << std::endl;

    // 不能复制 unique_ptr,但可以移动
    std::unique_ptr<int> uptr2 = std::move(uptr);

    if (!uptr) {
        std::cout << "uptr is now null" << std::endl;
    }

    // uptr2 现在拥有资源
    std::cout << "Value in uptr2: " << *uptr2 << std::endl;

    return 0;
}

2. std::shared_ptr

std::shared_ptr 是一种共享所有权的智能指针,允许多个 std::shared_ptr 同时指向同一个对象。每个 std::shared_ptr 都维护一个引用计数,当最后一个 std::shared_ptr 被销毁时,才会释放所管理的对象。

特点
  • 共享所有权:通过引用计数机制实现多个指针共享同一资源。
  • 线程安全:引用计数的操作是线程安全的。
示例
 

cpp

#include <iostream>
#include <memory>

void print_shared_ptr(std::shared_ptr<int> sptr) {
    std::cout << "Value: " << *sptr << ", Use count: " << sptr.use_count() << std::endl;
}

int main() {
    // 创建一个 shared_ptr
    std::shared_ptr<int> sptr = std::make_shared<int>(20);

    // 复制 shared_ptr
    std::shared_ptr<int> sptr2 = sptr;

    print_shared_ptr(sptr);  // 输出 Value: 20, Use count: 2
    print_shared_ptr(sptr2); // 输出 Value: 20, Use count: 2

    // 当 sptr 和 sptr2 都离开作用域时,引用计数变为 0,资源会被释放

    return 0;
}

3. std::weak_ptr

std::weak_ptr 是一种不控制对象生命周期的智能指针,通常与 std::shared_ptr 一起使用。它可以指向由 std::shared_ptr 管理的对象,但不会增加引用计数。因此,它不会阻止对象被销毁。

特点
  • 非持有所有权:不会影响对象的生命周期。
  • 解决循环引用问题:常用于解决 std::shared_ptr 之间的循环引用问题。
示例
#include <iostream>
#include <memory>

class Person {
public:
    std::shared_ptr<Person> mother;
    std::weak_ptr<Person> child;

    Person(const std::string& name) : name(name) {}

    void setMother(const std::shared_ptr<Person>& m) {
        mother = m;
        m->child = std::weak_ptr<Person>(this->shared_from_this());
    }

    void printInfo() {
        std::cout << name << "'s mother is ";
        if (mother.expired()) {
            std::cout << "no longer alive." << std::endl;
        } else {
            std::cout << mother.lock()->name << std::endl;
        }
    }

private:
    std::string name;
};

int main() {
    auto alice = std::make_shared<Person>("Alice");
    auto bob = std::make_shared<Person>("Bob");

    bob->setMother(alice);

    bob->printInfo(); // 输出 Bob's mother is Alice

    alice.reset(); // 释放 alice 的资源

    bob->printInfo(); // 输出 Bob's mother is no longer alive.

    return 0;
}

比较与选择

类型所有权模型是否允许复制是否线程安全适用场景
std::unique_ptr独占所有权不允许复制,但可以移动单一所有权管理
std::shared_ptr共享所有权允许复制多个指针共享资源
std::weak_ptr非持有所有权不直接持有资源解决循环引用问题

使用建议

  1. 优先使用 std::unique_ptr:除非确实需要共享所有权,否则应尽量使用 std::unique_ptr,因为它更高效且避免了不必要的复杂性。
  2. 使用 std::shared_ptr:当多个对象需要共享同一资源时,使用 std::shared_ptr 来确保资源的安全释放。
  3. 使用 std::weak_ptr:当需要避免循环引用时,使用 std::weak_ptr 来打破循环依赖。

总结

智能指针是现代C++编程中非常重要的工具,能够有效地管理动态分配的内存,减少内存泄漏和悬空指针的风险。理解并正确使用 std::unique_ptrstd::shared_ptrstd::weak_ptr 可以显著提高代码的健壮性和可维护性。

### C++ 智能指针详解 #### 定义与作用 智能指针是一种类模板,用于管理动态分配的对象生命周期。通过自动处理对象的创建和销毁,智能指针能够有效防止内存泄漏和其他资源管理错误。 #### 类型介绍 C++标准库提供了三种主要类型的智能指针: - **unique_ptr** `std::unique_ptr` 是一种独占所有权的智能指针,不允许复制操作,但支持移动语义[^1]。 ```cpp std::unique_ptr<int> ptr(new int(10)); ``` - **shared_ptr** `std::shared_ptr` 实现了引用计数机制,允许多个指针共享同一个对象实例。当最后一个指向该对象的 `shared_ptr` 被销毁或重置时,所管理的对象也会被删除[^2]。 ```cpp auto sptr = std::make_shared<int>(20); ``` - **weak_ptr** `std::weak_ptr` 不增加引用计数,通常作为辅助工具配合 `shared_ptr` 使用,主要用于解决循环引用问题[^3]。 ```cpp std::weak_ptr<int> wptr(sptr); ``` #### 应用场景示例 假设有一个简单的工厂模式实现,其中涉及到了不同种类的产品生产。为了简化代码并提高安全性,可以采用智能指针来代替原始裸指针。 ```cpp #include <memory> #include <iostream> // 基础产品接口定义 struct Product { virtual ~Product() {} virtual void use() const = 0; }; // 具体产品的实现之一 struct ConcreteProductA : public Product { void use() const override { std::cout << "Using product A\n"; } }; // 工厂函数返回智能指针而非普通指针 std::unique_ptr<Product> create_product_a() { return std::make_unique<ConcreteProductA>(); } int main() { // 自动管理内存,无需手动delete auto prod = create_product_a(); prod->use(); return 0; } ``` 上述例子展示了如何利用 `std::unique_ptr` 来安全地管理和传递堆上分配的对象,而不需要担心忘记释放资源的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平凡而伟大.

你们的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值