首页 > 解决方案 > 在容器中使用智能指针的原因

问题描述

简单写我想问“使用智能指针的好理由是什么?” 例如std::unique_ptr

但是,我并不是在询问使用智能指针而不是常规(哑)指针的原因。我想每个人都知道,或者快速搜索可以找到原因。

我要问的是这两种情况的比较:

给定一个名为MyObjectuse的类(或结构)

  1. std:queue<std::unique_ptr<MyObject>>queue;

而不是

  1. std:queue<MyObject> queue;

(可以是任何容器,不一定是队列)

为什么有人应该使用选项 1 而不是 2?

标签: c++c++11containerssmart-pointers

解决方案


这实际上是一个好问题。

我能想到的原因有几个:

  • 多态性仅适用于引用和指针,不适用于值类型。因此,如果您想将派生对象保存在您不能拥有的容器中std::queue<MyObject>。一个选项是unique_ptr,另一个是reference_wrapper

  • 包含的对象从容器外部引用 (*)。根据容器的不同,它包含的元素可以移动,从而使之前对它的引用无效。例如std::vector::insert或容器本身的移动。在这种情况下std::unique_ptr<MyObject>,确保引用是有效的,不管容器对它做了什么(ofc,只要它还unique_ptr活着)。
    在以下示例中,Objects您可以在队列中添加一堆对象。但是,其中两个对象可能是特殊的,您可以随时访问这两个对象。

    struct MyObject { MyObject(int); };
    
    struct Objects
    {
        std::queue<std::unique_ptr<MyObject>> all_objects_;
    
        MyObject* special_object_ = nullptr;
        MyObject* secondary_special_object_ = nullptr;
    
        void AddObject(int i)
        {
            all_objects_.emplace(std::make_unique<MyObject>(i));
        }
    
        void AddSpecialObject(int i)
        {
            auto& emplaced = all_objects_.emplace(std::make_unique<MyObject>(i));
            special_object_ = emplaced.get();
        }
    
        void AddSecondarySpecialObject(int i)
        {
            auto& emplaced = all_objects_.emplace(std::make_unique<MyObject>(i));
            secondary_special_object_ = emplaced.get();
        }
    };
    

(*) 我在这里使用“reference”的英文含义,而不是 C++ 类型。引用对象的任何方式(例如通过原始指针)


推荐阅读