22-x 第二十二章 内容提要与测验
智能指针类是一种组合类,旨在管理动态分配的内存,并确保当智能指针对象作用域结束时内存被释放。
复制语义允许我们的类被复制。这主要通过复制构造函数和复制赋值运算符实现。
移动语义意味着类将转移对象的所有权而非创建副本。这主要通过移动构造函数和移动赋值运算符实现。
std::auto_ptr 已被弃用,应避免使用。
右值引用是专为初始化右值而设计的引用类型,通过双重&符号创建。函数可接受右值引用参数,但几乎不应返回右值引用。
当构造对象或进行赋值操作时,若参数为左值,唯一合理做法是复制该左值。我们不能假设修改左值是安全的,因为程序后续可能再次使用该左值。例如表达式“a = b”中,我们合理预期b不会被修改。
然而,当构造对象或进行赋值时若参数为右值,则该右值本质上是某种临时对象。此时无需进行耗时的复制操作,只需将资源(成本低廉)转移至目标对象即可。此操作安全可靠,因为临时对象在表达式结束时必然被销毁,确保其资源绝不会被重复使用!
可通过删除复制构造函数和复制赋值运算符,使用delete关键字禁用自定义类的复制语义。
std::move允许将左值视为右值,这在需要对左值调用移动语义而非复制语义时尤为有用。
std::unique_ptr是推荐使用的智能指针类。它管理单个不可共享资源。创建新 std::unique_ptr 时应优先使用 C++14 引入的 std::make_unique()。该类禁用复制语义。
std::shared_ptr 是用于多对象共享资源的智能指针类。该资源将持续存在直至最后一个管理它的 std::shared_ptr 被销毁。创建新 std::shared_ptr 时应优先使用 std::make_shared()。使用 std::shared_ptr 时,应通过复制语义创建指向同一对象的额外 std::shared_ptr。
std::weak_ptr 是智能指针类,适用于需要一个或多个对象查看并访问由 std::shared_ptr 管理资源的情境。但与 std::shared_ptr 不同,在判断资源是否应被销毁时,std::weak_ptr 不被纳入考量。
测验时间
1.说明何时应使用下列指针类型:
1a) std::unique_ptr
显示答案
当需要智能指针管理不会被共享的动态对象时,应使用 `std::unique_ptr`。
1b) std::shared_ptr
显示答案
当需要智能指针管理可能被共享的动态对象时,应使用 std::shared_ptr。该对象在所有持有它的 std::shared_ptr 销毁之前都不会被释放。
1c) std::weak_ptr
显示答案
当需要访问由 std::shared_ptr 管理对象,但又不希望 std::shared_ptr 的生命周期与 std::weak_ptr 的生命周期绑定时,应使用 std::weak_ptr。
1d) std::auto_ptr
显示答案
std::auto_ptr 已被弃用,并在 C++17 中被移除。不应再使用它。
2.解释移动语义为何围绕右值展开。
显示解答
由于右值是临时对象,我们知道它们在使用后会被销毁。当按值传递或返回右值时,复制对象再销毁原件的做法效率低下。相反,我们可以直接移动(窃取)右值的资源,这种方式通常更高效。
3.下列代码存在何种问题?请按最佳实践规范更新程序。
3a)
#include <iostream>
#include <memory> // for std::shared_ptr
class Resource
{
public:
Resource() { std::cout << "Resource acquired\n"; }
~Resource() { std::cout << "Resource destroyed\n"; }
};
int main()
{
auto* res{ new Resource{} };
std::shared_ptr<Resource> ptr1{ res };
std::shared_ptr<Resource> ptr2{ res };
return 0;
}
显示解决方案
ptr2 是从 res 创建的,而非从 ptr1 创建。这意味着现在存在两个 std::shared_ptr,各自独立尝试管理该资源(彼此互不知情)。当其中一个超出作用域时,另一个将持有悬空指针。
应改为用ptr1初始化ptr2而非res。这样ptr1和ptr2就能共享res的所有权。应使用std::make_shared()替代手动动态分配。
#include <iostream>
#include <memory> // for std::shared_ptr
class Resource
{
public:
Resource() { std::cout << "Resource acquired\n"; }
~Resource() { std::cout << "Resource destroyed\n"; }
};
int main()
{
auto ptr1{ std::make_shared<Resource>() };
auto ptr2{ ptr1 };
return 0;
}

浙公网安备 33010602011771号