概述
智能指针作为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的重要性。
💡 如果想阅读最新的文章,或者有技术问题需要交流和沟通,可搜索并关注微信公众号“希望睿智”。