C++ 20新特性之进化的智能指针

206 阅读4分钟

概述

智能指针作为C++ 11中自动管理内存的重要工具,包括:std::unique_ptr、std::shared_ptr和std::weak_ptr等。C++ 20对这些智能指针做了进一步的优化和扩展,并引入了新的与内存管理和资源控制相关的功能。下面,我们对一些主要的优化点进行详细的介绍。

对unique_ptr的优化

1、可空构造和赋值。虽然之前版本的C++也允许通过传递nullptr来初始化或赋值给unique_ptr,但并不是明确的用法。C++ 20对此进行了明确,强调了这种用法的合法性,提高了代码的可读性。

#include <iostream>
using namespace std;

int main()
{
    // 直接初始化为nullptr
    unique_ptr<int> pData = nullptr;
    // 直接赋值为nullptr
    pData = nullptr;
    return 0;
}

2、显式bool转换。在C++ 20之前,unique_ptr已经可以通过隐式转换到bool来检查是否为空,但这并非语言标准明确规定的。C++ 20将其正式标准化,确保所有符合标准的编译器都支持这种用法。这意味着,我们可以直接将unique_ptr用在布尔上下文中检查它是否持有对象,就像下面的示例代码一样。

#include <iostream>
using namespace std;

int main()
{
    unique_ptr<int> pData;
    // 隐式转换到bool
    if (!pData)
    {
        cout << "pData is null" << endl;
    }

    return 0;
}

3、更强的类型推导。C++ 20增强了类型推导机制,使得在某些上下文中可以省略模板参数。虽然这不直接影响unique_ptr的定义,但它影响了如何使用make_unique等工厂函数,使得创建unique_ptr实例的代码更为简洁。在下面的示例代码中,不需要显式指定模板参数类型,编译器能够自动推断出正确类型。

#include <iostream>
using namespace std;

int main()
{
    // 利用类型推导简化unique_ptr的声明
    auto pData = make_unique<int>(666);
    if (pData)
    {
        cout << *pData << endl;
    }

    return 0;
}

对shared_ptr的优化

1、效率提升。C++ 20鼓励编译器对智能指针的构造和赋值操作进行优化,特别是对于make_shared和allocate_shared的使用,以减少内存分配次数,提升性能。

2、比较运算符的泛化。在C++ 20之前,shared_ptr只能与相同类型的另一个shared_ptr或nullptr进行比较,C++ 20则允许shared_ptr与原始指针进行比较。这提高了代码的灵活性,使得在需要检查shared_ptr是否与某个原始指针指向同一对象时更加便捷。

#include <iostream>
using namespace std;

int main()
{
    shared_ptr<int> pData = make_shared<int>(666);
    int* pRaw = pData.get();
    // 与原始指针直接进行比较
    if (pData == pRaw)
    {
        cout << "is same" << endl;
    }
    else
    {
        cout << "not same" << endl;
    }

    return 0;
}

3、直接动态数组。在C++ 20之前,shared_ptr本身并不直接支持动态数组的管理。当我们使用new[]来分配一个数组时,需要在销毁时使用delete[]而不是delete。而shared_ptr的默认删除器只会调用delete,这会导致数组分配的内存无法正确释放。为了使用shared_ptr管理动态数组,我们需要提供一个自定义的删除器,通常是delete[],以确保数组能够被正确地释放,类似下面的示例代码。

shared_ptr<int> pData(new int[6], [](int* p) { delete[] p; });

C++ 20允许在构造函数中省略删除器模板参数。此时,编译器会自动推断,并使用正确的默认删除器,使得代码更简洁。

shared_ptr<int> pData(new int[6]);

对weak_ptr的优化

1、C++ 20对weak_ptr的改进虽然不如对shared_ptr和unique_ptr那么显著,但依然包含了一些增强,主要是为了提高其使用上的灵活性和效率。比如:类型推导的改进,使得在某些上下文中使用weak_ptr更加简洁。

2、明确了与atomic的集成。虽然atomic<weak_ptr>并不是C++ 20中引入的新特性,但C++ 20对原子操作的支持和文档表述更加明确,强调了在多线程环境下安全地访问和修改weak_ptr的重要性。

💡 如果想阅读最新的文章,或者有技术问题需要交流和沟通,可搜索并关注微信公众号“希望睿智”。