【问题标题】:How to handle STL container with elements of classes containing large arrays of data如何使用包含大型数据数组的类元素来处理 STL 容器
【发布时间】:2011-06-14 04:57:40
【问题描述】:

我正在寻找一种方法将大型数据数组(存储在具有基本功能的类中,例如检查数据、大小等)放入任何 STL 容器中,例如向量或队列(FIFO 队列是最好的,因为我有一个生产者和一个消费者)。

问题是我必须实现复制构造函数并且......好吧..我不想制作深拷贝(因为它需要太多时间,所以我坚持浅拷贝),但又一次我有不知道何时删除析构函数中的数据数组的问题(因为我两次调用析构函数并且只有一次数据,另外,对析构函数的第一次调用可能来自在容器中插入/移动元素,所以那时我仍然需要数组数据)。

我考虑过对数据数组使用像 std::shared_ptr 这样的智能指针,但从我读到的内容来看,它们不调用 delete [] 而是调用 delete - 这是一种耻辱,因为我有一个普通的数组 []。

现在我有一个解决方案,可以在将类从容器中删除之前手动调用类上的“DeleteArray”函数。它工作得很好,但是......它不是很好。

有什么想法吗?

【问题讨论】:

    标签: c++ arrays performance stl large-data


    【解决方案1】:

    Boost 有一个类似于shared_ptrshared_array 类,但将使用delete[],或者您可以向shared_ptr 添加自定义删除器,使其调用delete[]

    【讨论】:

      【解决方案2】:

      不要使用数组,而是使用std::vector。然后用智能指针指向它。

      【讨论】:

      • 这为访问增加了一层额外的间接层:您将在堆中有一堆vectors,每个都指向位于不同位置的单独数据数组堆。
      • @Jeremiah:没错,但不比容器类的任何其他用途更重要。
      • @Oli:当使用vector<shared_ptr<vector<...> > > 时,您将拥有一个指向单个vector 对象的vector 指针(每个对象只有几个内存字),并且每个对象将指向一个单独的数据数组。使用 shared_array 之类的东西会删除其中一个间接级别。
      • @Jeremiah:也许我们在谈论不同的目的。而不是int *pArray 作为班级成员(正如OP 正在考虑的那样),我提倡shared_ptr<vector<int> > spVec。我不确定您的评论中vector 的第二层来自哪里。
      • @Oli:这也是我的意思——问题是说会有一个大型数组的 STL 容器,所以你建议用 vector<shared_ptr<vector<int> > > 替换像 vector<int*> 这样的东西。还是我误会了?
      【解决方案3】:

      更好的解决方案是将shared_ptrs 放到您的大对象到容器中,并避免将昂贵的副本放在一起。

      编辑 0:

      当然,另一种选择是使用shared_array 使对象本身轻量且可复制。正如耶利米建议的那样。

      【讨论】:

      • 不胜感激对否决投票的解释。
      • 已经使用shared_ptr 提到的问题,以及明显的问题。
      • 问题提到在大对象中对成员数组使用shared_ptr
      • 问题中提到的大对象是数据数组。
      • “存储在一个类中,包含检查数据、大小等基本功能”,嗯?
      【解决方案4】:

      至少在 Boost 库中,数组有一个 shared_ptr 等效项。它被称为shared_array,它的行为完全符合您的预期。在http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/shared_array.htm?sess=8940ad57baa307d68cb2e7fd2939d2db查看规范。

      【讨论】:

        【解决方案5】:

        您可以在复制构造函数中实现简单的引用计数。您可以在每次删除时减少引用。

        【讨论】:

          【解决方案6】:

          非常感谢您所有有见地的回答!

          这提醒了我为什么上次遇到这个问题时,我在没有复制自己的情况下手动编写了一个队列。我不能说我花费的时间比弄清楚如何制作漂亮、干净的版本花费的时间要长得多。 :)

          所以..我所做的是:

          解决方案 a) 就像在原始帖子中描述的那样,我创建了一个必须在从向量中删除类之前显式调用的函数。不太好,但效果很好,我不必乱搞其他任何东西,只要记住调用它。

          解决方案 b) 我将数组放在另一个类中,并对该类使用了智能指针(shared_ptr)。工作得非常好。我也必须使用 shared_ptr 作为向量的元素。 (一开始我没有想到。)

          解决方案 c) 使用 shared_ptr 来保存一个数组。事实证明这是一个非常糟糕的主意,因为它调用 delete 而不是 delete [] 您需要提供您的自定义删除器,并且不知何故出现了一些其他(语法)问题,所以我花了 2h+ 之类的时间来解决这个问题。

          在头文件中看起来像这样:

           template< typename T >
            struct
          array_deleter
            {
                void
              operator ()( T const * p)
                { delete[] p; }
            };
          
          class MemoryStressChunk
          {
          private:
              int chunkSizeInValues;
              std::shared_ptr< __int64 > data;
          };
          

          在代码文件中:

          data.reset(
              new __int64[chunkSizeInValues], 
              array_deleter< __int64 >() );
          

          要使用它,我必须再次取出它:

          __int64 *d = data.get();
          

          下次我可能会强烈考虑使用增强版本。我的机器上没有增强功能,所以这就是为什么它不适合我。

          我接受 解决方案 d) 将使用包含 shared_ptr 的类向量到向量(而不是数组)。毕竟我和 c) 玩得很开心,但我并没有这样做。 :)

          如果有人想看代码,你可以在这里http://andreas-reiff.de/wp-content/uploads/2011/01/Tool-MemTester.zip 获取。请注意版本 a) 中可能存在 memleak(使用 shared_ptr 作为版本 b) 中的类)。

          再次感谢您的帮助!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-08-14
            • 2016-02-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多