将智能指针与容器一起使用的原因



简单地写成,我想问"使用智能指针的好理由是什么? 对于前std::unique_ptr

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

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

给定一个名为MyObject使用的类(或结构(

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

而不是

  1. std:queue<MyObject> queue;

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

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

这实际上是一个很好的问题。

我能想到的有几个原因:

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

(*(我在这里使用的"参考"是英文意思,而不是C++类型。引用对象的任何方式(例如,通过原始指针(

用例:您希望在具有常量索引的std::vector中存储某些内容,同时能够从该向量中删除对象。

如果使用指针,则可以删除指向的对象并设置vector[i] = nullptr,(稍后还要检查它(,这是存储对象本身时无法执行的操作。如果你存储对象,你必须将实例保留在向量中并使用标志bool valid或其他东西,因为如果你从向量中删除一个对象,那么该对象的索引后的所有索引都会改变 -1。


注意:如此答案的评论中所述,如果您可以访问 C++17 或更高版本,则可以使用std::optional进行存档。

第一个声明生成一个包含指针元素的容器,第二个声明生成纯对象。

以下是在对象上使用指针的一些好处:

  1. 它们允许您创建动态大小的数据结构。
  2. 它们允许您直接操作内存(例如在打包或 从硬件设备解压缩数据。
  3. 它们允许对象引用(函数或数据对象(
  4. 它们允许您操作对象(通过 API(,而无需知道对象的详细信息(API 除外(。
  5. (原始(指针通常与 CPU 寄存器匹配良好,这使得通过指针取消引用值非常有效。(C++"智能"指针是更复杂的数据对象。

此外,多态性被认为是面向对象编程的重要特征之一。 在C++多态性主要分为两种类型:

  • 编译时多态性

这种类型的多态性是通过函数重载或运算符重载实现的。

  • 运行时多态性

这种类型的多态性是通过函数覆盖实现的,如果我们想使用基类来使用这些函数,就必须使用指针而不是对象。

相关内容

  • 没有找到相关文章

最新更新