【问题标题】:Vectors with fixed dimension and values (C++)具有固定维度和值的向量 (C++)
【发布时间】:2010-10-11 10:41:51
【问题描述】:

我想知道存储向量/数据数组(int 或 double)的性能方面的最佳解决方案,其维度在编译时不可用(取决于用户的输入),但一旦初始化,他们永远不会改变他们的维度,也不会改变他们的价值观。换句话说,我想知道是否使用与向量不同的东西可以提高效率,因为我确信向量的尺寸和内容在初始化后永远不会改变。 谢谢 阿尔贝托

【问题讨论】:

  • 效率是什么意思?访问单个元素的成本 ?是什么让您认为这是一个问题?你有没有分析你的代码来验证这个假设?
  • 内置数据类型不会妨碍向量中的插入、修改或删除。
  • .. 确切地说,你为什么认为std::vector 可能不够?
  • 由于向量具有恒定的访问时间,我认为这是你最好的选择

标签: c++ vector


【解决方案1】:

尽管问题中暗示了怀疑,但我仍然会尝试使用std::vector(除非另有证明)并在我知道用户维度后立即调用成员函数reserve()为所有元素分配空间输入。预先调用reserve() 可以避免重复的内存分配和元素复制。

【讨论】:

  • 我同意,但如果尺寸确实是固定的,您可能需要调用“resize”而不是“reserve”。那么您可以使用每个元素,而永远不要调用“push_back”。
  • @edA-qa mort-ora-y: IIRC, resize() 会调用元素的默认构造函数,但reserve() 不会。在这种特殊情况下,元素是intdouble,这可能无关紧要,但我认为这是一个好习惯。而且,reserve()被适当调用后,push_back()等价于数组索引vec[ i ] = new_elem
  • 不,push_back(x) 不等于 vec[i] = x。使用超出数组size的索引是无效的,即使它在容量之内。
  • @Mike Seymour:你是对的,但我没有说i 是什么:)。它可能是增加的大小。我想在评论中传达的是,如果 reserve() 被适当地调用,那么 push_backs 将永远不会调用内存分配和复制,它们将“等同于”分配给数组元素。
  • 如果您预先“调整大小”,则以后不会有任何性能成本。该标准确实缺少“resize_no_init”功能;这通常是最好的选择。
【解决方案2】:

好吧,如果你不改变向量的大小,那么你就不会有重新分配的开销。所以vector仍然是一个不错的选择。如果数据也不会改变,你可以使用 const 向量

【讨论】:

    【解决方案3】:

    std::vector 很好。如果您尝试使用其中的数字进行数学运算,std::valarray 可能是一个不错的选择。它也可以修改和调整大小,但只要您不使用它,实现就不会为此产生任何开销。

    【讨论】:

      【解决方案4】:

      如果初始化后大小和内容确实从未改变,则使用const vector。但是,如果内容很有趣,这意味着您将不得不使用复制构造函数,或者使用迭代器对的构造函数。

      在优化方面不太可能实现很多,但值得一试[*]。但是,它会强制您的代码是 const 正确的,也就是说,您不仅不能修改向量,而且您的代码必须对编译器构成一种特定类型的 proof (除非不明智的强制转换) 你不修改向量。

      这是额外的工作,如果您的代码已经不是 const 正确的,但是随着您的进行,编译器会告诉您需要更改的内容。

      [*] 我想我的意思是,作为一般惯例,在可能的情况下使用const 是值得的。不过,其原因与性能没有太大关系。如果您只是想加快某个特定程序的速度,那么开发人员的时间比修改不是 const 正确的代码更有效地使用,以使其成为 const 正确的。但假设它可以编译,则无需进行任何更改。

      【讨论】:

        【解决方案5】:

        您的替代选项是 boost::shared_array。它们也是引用计数的,因此您可以在不复制数据的情况下复制 shared_array。

        shared_array 是有限的:你不能从中获取大小,也不能通过传递 shared_array 来保护你的数据。

        所以要做到这一点,您必须编写一个可以同时执行这两个操作的包装器。如果你要写一个包装器,你可以只包装 shared_ptr > 但这意味着更多的分配和更多的间接,所以 shared_array 可能是你的朋友。

        shared_array 不是 tr1 的一部分。

        要使用 shared_array,您以“旧”方式分配数据,即在需要数据时使用 new T[N],但 shared_array 保护它的生命周期,因此您不必担心删除它(如只要你不做循环引用)。

        【讨论】:

          【解决方案6】:

          在整数/双精度列表中使用它们,例如here

          【讨论】:

          • 那个例子很丑。缩进不好,没有 cmets,.h 标头,危险的默认复制构造函数和operator=,调用“列出”一个数组,不重载operator[],甚至不让调用者处理存储的对象,混合容器-带有 UI 逻辑的逻辑...
          • 这只是一个想法:),我没有给出复制粘贴到代码中的示例,我给出它是为了产生想法并考虑它
          • 我完全理解,但是如果你提供一个例子,它应该只显示基本概念是可以的,但它不应该充满错误和不良做法:)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多