智能指针与移动语义:测验与小结

智能指针类是一种组合类,专门用于管理动态分配的内存,并在智能指针对象离开作用域时确保该内存被释放。

拷贝语义允许我们的类被复制,主要通过拷贝构造函数和拷贝赋值运算符实现。

移动语义意味着类将转移对象的所有权,而非进行复制,主要通过移动构造函数和移动赋值运算符完成。

std::auto_ptr 已被弃用,应避免使用。

右值引用是一种专为接受右值而设计的引用,使用双与号(&&)声明。虽然可以编写以右值引用为形参的函数,但几乎绝不应返回右值引用。

如果我们用左值构造对象或执行赋值,唯一能合理执行的操作就是复制该左值——我们无法安全地修改它,因为程序后续可能还要使用。例如表达式 a = b 中,我们绝不会期望 b 被改变。

然而,如果我们用右值构造对象或执行赋值,则该右值只是某种临时对象。此时与其进行(可能昂贵的)复制,不如将其资源(以低廉的成本)直接转移给正在构造或赋值的对象。这样做是安全的,因为临时对象在表达式结束时就会被销毁,我们确信它再也不会被使用!

可使用关键字 delete 显式禁用类的拷贝语义:将拷贝构造函数与拷贝赋值运算符标记为已删除即可。

std::move 允许将左值“视”为右值,从而在左值上触发移动语义而非拷贝语义。

std::unique_ptr 应是你首选的智能指针。它管理唯一的、不可共享的资源。创建新的 std::unique_ptr 时,应优先使用 C++14 引入的 std::make_unique()。std::unique_ptr 禁止拷贝语义。

std::shared_ptr 用于需要多个对象共享同一资源的场景。仅当最后一个管理该资源的 std::shared_ptr 被销毁时,资源才会被释放。创建新的 std::shared_ptr 时,应优先使用 std::make_shared()。对于已存在的对象,应使用拷贝语义创建指向同一对象的额外 std::shared_ptr。

std::weak_ptr 用于需要查看或访问由 std::shared_ptr 管理之资源的情形;与 std::shared_ptr 不同的是,在决定是否销毁资源时,std::weak_ptr 不计入引用计数。

测验

请说明以下指针类型应在何时使用:

1a) std::unique_ptr

展示解答

1b) std::shared_ptr

展示解答

1c) std::weak_ptr

展示解答

1d) std::auto_ptr

展示解答

请解释为何移动语义围绕右值展开。

展示解答

下列代码存在哪些问题?请将其改写为符合最佳实践的版本。

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;
}

关注公众号,回复"cpp-tutorial"

可领取价值199元的C++学习资料

公众号二维码

扫描上方二维码或搜索"cpp-tutorial"