C++ 智能指针

智能指针是 C++ 中的一种数据结构,用于管理动态分配的内存资源,以减少内存泄漏和悬空指针等问题。智能指针在 C++11 标准中引入,并且是标准库中的一部分。它们通过在内部封装原始指针,并提供额外的功能来提高内存管理的安全性和效率。

常见的智能指针有 std::unique_ptr、std::shared_ptr 和 std::weak_ptr。

std::unique_ptr

  1. 独占所有权:std::unique_ptr 不能被复制,只能通过移动来转移所有权。
#include <memory>
#include <iostream>

int main() {
    // 创建一个独占所有权的 unique_ptr
    std::unique_ptr<int> uniquePtr(new int(42));

    // 尝试复制 unique_ptr 会导致编译错误
    // std::unique_ptr<int> anotherPtr = uniquePtr; // 错误

    // 可以通过移动来转移所有权
    std::unique_ptr<int> anotherPtr = std::move(uniquePtr);

    // uniquePtr 不再拥有资源
    if (!uniquePtr) {
        std::cout << "uniquePtr 不再拥有资源" << std::endl;
    }

    return 0;
}
  1. 资源自动释放:当 std::unique_ptr 被销毁时,它所管理的资源会被自动释放,无需手动释放资源。
#include <memory>
#include <iostream>

int main() {
    {
        // 创建一个独占所有权的 unique_ptr
        std::unique_ptr<int> uniquePtr(new int(42));
    } // uniquePtr 超出作用域,资源自动释放

    std::cout << "资源已释放" << std::endl;

    return 0;
}
  1. 适合用于动态分配的单一对象或对象数组的所有权管理:std::unique_ptr 可以管理单个对象或对象数组的动态分配内存。
#include <memory>
#include <iostream>

int main() {
    // 创建一个独占所有权的 unique_ptr,用于动态分配单个对象
    std::unique_ptr<int> singleObjectPtr(new int(42));

    // 创建一个独占所有权的 unique_ptr,用于动态分配对象数组
    std::unique_ptr<int[]> arrayPtr(new int[5]{1, 2, 3, 4, 5});

    // 使用 unique_ptr 访问动态分配的对象或对象数组
    std::cout << *singleObjectPtr << std::endl; // 输出 42
    std::cout << arrayPtr[2] << std::endl;      // 输出 3

    return 0;
}

std::shared_ptr

  1. 共享所有权:std::shared_ptr 可以被多个 std::shared_ptr 实例共享。
#include <memory>
#include <iostream>

int main() {
    // 创建一个共享所有权的 shared_ptr,初始引用计数为1
    std::shared_ptr<int> sharedPtr1(new int(42));

    // 创建另一个 shared_ptr,与前一个共享同一个资源
    std::shared_ptr<int> sharedPtr2 = sharedPtr1;

    // 输出引用计数
    std::cout << "sharedPtr1 引用计数: " << sharedPtr1.use_count() << std::endl;
    std::cout << "sharedPtr2 引用计数: " << sharedPtr2.use_count() << std::endl;

    return 0;
}
  1. 使用引用计数管理资源:std::shared_ptr 使用引用计数来管理资源,当最后一个 std::shared_ptr 被销毁时,资源被释放。
#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> sharedPtr(new int(42));

    // 输出引用计数
    std::cout << "初始引用计数: " << sharedPtr.use_count() << std::endl;

    {
        // 创建另一个 shared_ptr,引用计数增加
        std::shared_ptr<int> anotherPtr = sharedPtr;
        std::cout << "引用计数增加后: " << sharedPtr.use_count() << std::endl;
    } // anotherPtr 超出作用域,引用计数减少

    // 输出引用计数
    std::cout << "引用计数减少后: " << sharedPtr.use_count() << std::endl;

    return 0;
}
  1. 可能存在循环引用的问题:当两个或多个对象之间相互持有 std::shared_ptr,可能会导致循环引用,从而导致资源无法释放,产生内存泄漏。
#include <memory>

class A;
class B;

class A {
public:
    std::shared_ptr<B> bPtr;
};

class B {
public:
    std::shared_ptr<A> aPtr;
};

int main() {
    std::shared_ptr<A> aPtr(new A);
    std::shared_ptr<B> bPtr(new B);

    // 循环引用,导致资源无法释放
    aPtr->bPtr = bPtr;
    bPtr->aPtr = aPtr;

    return 0;
}

std::weak_ptr

std::weak_ptr 是一种弱引用智能指针,它不会增加资源的引用计数。

主要用于解决 std::shared_ptr 的循环引用问题,避免因循环引用导致的内存泄漏。

std::weak_ptr 不能直接访问资源,需要通过调用 lock() 方法获取一个指向资源的 std::shared_ptr,然后才能访问资源。

下面演示了如何使用 std::weak_ptr 解决循环引用问题:

#include <memory>
#include <iostream>

class B; // 前置声明

class A {
public:
    std::weak_ptr<B> bWeakPtr; // 使用 weak_ptr 避免循环引用
};

class B {
public:
    std::shared_ptr<A> aSharedPtr;
};

int main() {
    // 创建 shared_ptr 对象
    std::shared_ptr<A> aSharedPtr(new A);
    std::shared_ptr<B> bSharedPtr(new B);

    // 使用 weak_ptr 避免循环引用
    aSharedPtr->bWeakPtr = bSharedPtr;
    bSharedPtr->aSharedPtr = aSharedPtr;

    // 通过 lock() 方法获取 shared_ptr,然后访问资源
    if (auto sharedPtr = aSharedPtr->bWeakPtr.lock()) {
        // 访问资源
    }

    return 0;
}

通过将其中一个指针声明为 std::weak_ptr,可以防止循环引用。然后,可以通过调用 lock() 方法获取一个指向资源的 std::shared_ptr,然后使用该 shared_ptr 访问资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值