在容器中使用智能指针的原因

Kan*_*bot 4 c++ containers smart-pointers c++11

简单写我想问“使用智能指针的充分理由是什么?” 前任std::unique_ptr

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

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

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

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

而不是

  1. std:queue<MyObject> queue;

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

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

bol*_*lov 6

这其实是个好问题。

我能想到的原因有几个:

  • 多态仅适用于引用和指针,不适用于值类型。因此,如果您想将派生对象保存在容器中,则不能拥有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();
        }
    };
    
    Run Code Online (Sandbox Code Playgroud)

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