C++11中的智能指针

简介

本文介绍C++11中的智能指针的基本用法和运用场景

三种指针概述

在C++中,有三种智能指针,分别是:unique_ptr、shared_ptr和weak_ptr。这三种智能指针都是在STL的头文件< memory> 中定义的,可以在C++11及其以上版本中使用。

unique_ptr

unique_ptr是一种独占型智能指针,它的主要作用是管理动态分配的对象。unique_ptr类的特点是:只能有一个unique_ptr指向同一个对象,当此unique_ptr离开作用域时,其所指向的对象也会被自动释放。因为只有一个指针可以指向对象,所以可以保证指针不会被误用,进而避免内存泄漏等问题。

使用方法:

std::unique_ptr<Type> ptr(new Type(args...)); // 使用new表达式创建一个动态分配的对象,并将其托管给unique_ptr

示例代码如下:

#include <iostream>
#include <memory>

class Test {
public:
    Test() { std::cout << "Test Constructor" << std::endl; }
    ~Test() { std::cout << "Test Destructor" << std::endl; }
};

int main() {
    std::unique_ptr<Test> ptr(new Test());

    // 使用智能指针操作对象
    std::cout << "Unique pointer is " << (ptr ? "not null" : "null") << std::endl;

    return 0;
}

在上述代码中,我们定义了一个名为Test的类,并在main函数中使用unique_ptr动态分配了一个对象。可以看到,当程序执行到离开作用域时,会自动调用Test对象的析构函数,输出如下:

Test Constructor
Unique pointer is not null
Test Destructor

shared_ptr

shared_ptr是一种共享型智能指针,它的主要作用是管理动态分配的对象,并与其他shared_ptr共享这个对象的所有权。每个shared_ptr内部维护一个引用计数器,记录当前共享此对象的指针数目。当引用计数器变为0时,该对象将被自动释放。
使用方法:

std::shared_ptr<Type> ptr1 = std::make_shared<Type>(args...); // 使用make_shared函数创建一个动态分配的对象,并将其托管给shared_ptr
std::shared_ptr<Type> ptr2(ptr1); // 创建一个新的shared_ptr,与ptr1共享所有权

示例代码如下:

#include <iostream>
#include <memory>

class Test {
public:
    Test(int value) : mValue(value) { std::cout << "Test Constructor with value: " << value << std::endl; }
    ~Test() { std::cout << "Test Destructor with value: " << mValue << std::endl; }
    void SetValue(int value) { mValue = value; }
    int GetValue() const { return mValue; }

private:
    int mValue;
};

void PrintSharedPtrInfo(const std::shared_ptr<Test>& ptr) {
    std::cout << "Shared pointer value is: " << ptr->GetValue() << ", use count is: " << ptr.use_count() << std::endl;
}

int main() {
    std::shared_ptr<Test> ptr1 = std::make_shared<Test>(10);
    std::shared_ptr<Test> ptr2 = ptr1; // ptr2和ptr1共享所有权

    PrintSharedPtrInfo(ptr1);
    PrintSharedPtrInfo(ptr2);

    ptr1->SetValue(100);

    PrintSharedPtrInfo(ptr1);
    PrintSharedPtrInfo(ptr2);

    return 0;
}

在上述代码中,我们定义了一个名为Test的类,并在main函数中使用shared_ptr动态分配了一个对象,并使用两个shared_ptr对象共享其所有权。通过输出它们的值和引用计数,我们可以看到它们都共享同一个对象。同时,我们也可以修改这个对象的值,然后再次输出,可以发现修改后的值对两个shared_ptr对象都是可见的。输出如下:

Test Constructor with value: 10
Shared pointer value is: 10, use count is: 2
Shared pointer value is: 10, use count is: 2
Shared pointer value is: 100, use count is: 2
Shared pointer value is: 100, use count is: 2
Test Destructor with value: 100

weak_ptr

weak_ptr是一种弱引用智能指针,其主要作用是解决shared_ptr的循环引用问题。由于shared_ptr是共享型智能指针,当两个shared_ptr对象相互引用时,容易形成循环引用,导致内存泄漏等问题。weak_ptr可以创建一个对shared_ptr对象的非拥有性引用,并且不会导致引用计数加1,这样可以避免循环引用问题。
使用方法:

std::weak_ptr<Type> ptr; // 创建一个空的weak_ptr对象
std::shared_ptr<Type> sharedPtr = std::make_shared<Type>(args...);
ptr = sharedPtr; // 将shared_ptr赋值给weak_ptr
std::shared_ptr<Type> sharedPtr2 = ptr.lock(); // 使用lock函数获取可用的shared_ptr对象

ps:需要注意的是,weak_ptr所指向的对象可能已被其他原因销毁,此时lock函数返回一个空的shared_ptr对象。在使用shared_ptr之前,应该先检查它是否为空
示例代码如下:

#include <iostream>
#include <memory>

class Test;

void PrintWeakPtrInfo(const std::weak_ptr<Test>& ptr) {
    std::cout << "Weak pointer is " << (ptr.expired() ? "expired" : "not expired") << std::endl;
}

class Test {
public:
    Test(int value) : mValue(value) { std::cout << "Test Constructor with value: " << value << std::endl; }
    ~Test() { std::cout << "Test Destructor with value: " << mValue << std::endl; }

    void SetNext(std::weak_ptr<Test> next) {
        mNext = next;
    }
    std::weak_ptr<Test> GetNext() const {
        return mNext;
    }

private:
    int mValue;
    std::weak_ptr<Test> mNext;
};

int main() {
    std::shared_ptr<Test> ptr1 = std::make_shared<Test>(10);
    std::shared_ptr<Test> ptr2 = std::make_shared<Test>(20);

    // 使用weak_ptr解决shared_ptr循环引用问题
    ptr1->SetNext(ptr2);
    ptr2->SetNext(ptr1);

    PrintWeakPtrInfo(ptr1->GetNext());
    PrintWeakPtrInfo(ptr2->GetNext());

    // 获取对象的shared_ptr,如果对象已经被销毁则返回null
    std::shared_ptr<Test> sharePtr1 = ptr1->GetNext().lock();
    std::shared_ptr<Test> sharePtr2 = ptr2->GetNext().lock();

    if (sharePtr1) {
        std::cout << "Share pointer value is: " << sharePtr1->GetValue() << std::endl;
    } else {
        std::cout << "Share pointer is not available" << std::endl;
    }

    if (sharePtr2) {
        std::cout << "Share pointer value is: " << sharePtr2->GetValue() << std::endl;
    } else {
        std::cout << "Share pointer is not available" << std::endl;
    }

    return 0;
}

在上述代码中,我们定义了一个名为Test的类,并在main函数中使用两个shared_ptr动态分配了两个对象。然后,我们通过调用SetNext函数建立了两个对象之间的循环引用关系。接着,我们使用weak_ptr对象打破循环引用,获取这两个对象的下一个指针,并输出弱引用指针的状态。最后,我们使用lock函数获取可用的shared_ptr对象,并输出其值。由于测试程序没有显式释放内存,因此在程序结束时自动调用析构函数删除对象。输出如下:

Test Constructor with value: 10
Test Constructor with value: 20
Weak pointer is not expired
Weak pointer is not expired
Share pointer value is: 20
Share pointer value is: 10
Test Destructor with value: 10
Test Destructor with value: 20

三种指针的适用场景

1、unique_ptr是一种独占式智能指针,它管理着一个动态分配的对象,并确保在离开作用域时销毁该对象。它不能拷贝,只能移动,因此每个unique_ptr对象都是独一无二的。unique_ptr适用于需要在一个作用域内拥有一个对象的情况,例如函数中分配的临时对象或者容器中的元素。
2、shared_ptr是一种共享式智能指针,它也管理着一个动态分配的对象,并可以被多个shared_ptr对象共享所有权。它采用引用计数的方式来管理对象的生命周期,在所有shared_ptr对象都失效后才会销毁对象。shared_ptr适用于需要多个对象共享同一份数据的情况,例如多线程环境中的数据共享和实现观察者模式等。
3、weak_ptr是一种弱引用智能指针,它不对对象的生命周期产生影响,只是通过与shared_ptr对象配合使用,提供一种解决shared_ptr循环引用问题的方法。weak_ptr可以从一个shared_ptr或另一个weak_ptr对象构造而来,并且可以判断其指向的对象是否还存在,但是不能直接访问其指向的对象,需要调用lock()函数获取一个可用的shared_ptr对象。

总结

总之,选择何种智能指针取决于具体场景。如果需要拥有对象的独占权,那么应该选择unique_ptr;如果需要共享对象所有权,那么应该选择shared_ptr;如果需要打破shared_ptr循环引用,那么应该选择weak_ptr。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值