代码之家  ›  专栏  ›  技术社区  ›  KansaiRobot

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

  •  0
  • KansaiRobot  · 技术社区  · 4 年前

    简单来说,我想问“使用智能指针的一个好理由是什么?” 对于ex std::unique_ptr

    然而,我并不是在问使用智能指针的原因 超过常规(愚蠢)指针 我想每个人都知道,或者快速搜索就能找到原因。

    我想问的是这两个案例的比较:

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

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

    而不是

    1. std:queue<MyObject> queue;

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

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

    1 回复  |  直到 4 年前
        1
  •  7
  •   bolov    4 年前

    这其实是个好问题。

    我能想到几个原因:

    • 多态性仅适用于引用和指针,不适用于值类型。因此,如果你想在容器中保存派生对象,你不能拥有 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++类型。引用对象的任何方式(例如通过原始指针)

        2
  •  0
  •   nada    4 年前

    用例:你想把东西存储在 std::vector 同时能够从该向量中删除对象。

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


    注意:正如对此答案的评论中提到的,同样可以使用 std::optional ,如果您可以访问C++17或更高版本。

        3
  •  -2
  •   Mohammad Moridi    4 年前

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

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

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

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

    • 编译时多态性

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

    • 运行时多态性

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