向量:初始化还是保留?

新手上路,请多包涵

我知道向量的大小,这是初始化它的最佳方法吗?

选项1:

 vector<int> vec(3); //in .h
vec.at(0)=var1;     //in .cpp
vec.at(1)=var2;     //in .cpp
vec.at(2)=var3;     //in .cpp

选项 2:

 vector<int> vec;     //in .h
vec.reserve(3);      //in .cpp
vec.push_back(var1); //in .cpp
vec.push_back(var2); //in .cpp
vec.push_back(var3); //in .cpp

我猜,Option2 比 Option1 好。是吗?还有其他选择吗?

原文由 Ale 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 684
2 个回答

两种变体都有不同的语义,即您正在比较苹果和橙子。

第一个为您提供 n 个默认初始化值的向量,第二个变体保留内存,但不初始化它们。

选择更适合您需要的,即在特定情况下什么是“更好的”。

原文由 Sebastian Mach 发布,翻译遵循 CC BY-SA 3.0 许可协议

不知何故,一个完全错误的非答案答案在大约 7 年的时间里一直被接受并获得最多支持。这不是一个苹果和橘子的问题。这不是一个可以用模糊的陈词滥调来回答的问题。

要遵循一个简单的规则:

选项 #1 更快… 在此处输入图像描述 在此处输入图像描述

…但这可能不是您最关心的问题。

首先,差异很小。其次,随着我们加快编译器优化,差异变得更小。例如,在我的 gcc-5.4.0 上,当运行 3 级编译器优化 ( -O3 ) 时,差异可以说是微不足道的: 在此处输入图像描述

所以一般来说,每当遇到这种情况时,我都会推荐使用方法#1。但是,如果您不记得哪个是最佳的,则可能不值得努力找出。只需选择其中一个并继续前进,因为这不太可能导致整个程序明显放缓。


这些测试是通过从正态分布中采样随机向量大小来运行的,然后使用这两种方法对这些大小的向量的初始化进行计时。我们保留一个虚拟和变量以确保向量初始化不会被优化,并且我们随机化向量大小和值以努力避免由于分支预测、缓存和其他此类技巧引起的任何错误。

main.cpp

 /*
 * Test constructing and filling a vector in two ways: construction with size
 * then assignment versus construction of empty vector followed by push_back
 * We collect dummy sums to prevent the compiler from optimizing out computation
 */

#include <iostream>
#include <vector>

#include "rng.hpp"
#include "timer.hpp"

const size_t kMinSize = 1000;
const size_t kMaxSize = 100000;
const double kSizeIncrementFactor = 1.2;
const int kNumVecs = 10000;

int main() {
  for (size_t mean_size = kMinSize; mean_size <= kMaxSize;
       mean_size = static_cast<size_t>(mean_size * kSizeIncrementFactor)) {
    // Generate sizes from normal distribution
    std::vector<size_t> sizes_vec;
    NormalIntRng<size_t> sizes_rng(mean_size, mean_size / 10.0);
    for (int i = 0; i < kNumVecs; ++i) {
      sizes_vec.push_back(sizes_rng.GenerateValue());
    }
    Timer timer;
    UniformIntRng<int> values_rng(0, 5);
    // Method 1: construct with size, then assign
    timer.Reset();
    int method_1_sum = 0;
    for (size_t num_els : sizes_vec) {
      std::vector<int> vec(num_els);
      for (size_t i = 0; i < num_els; ++i) {
        vec[i] = values_rng.GenerateValue();
      }
      // Compute sum - this part identical for two methods
      for (size_t i = 0; i < num_els; ++i) {
        method_1_sum += vec[i];
      }
    }
    double method_1_seconds = timer.GetSeconds();
    // Method 2: reserve then push_back
    timer.Reset();
    int method_2_sum = 0;
    for (size_t num_els : sizes_vec) {
      std::vector<int> vec;
      vec.reserve(num_els);
      for (size_t i = 0; i < num_els; ++i) {
        vec.push_back(values_rng.GenerateValue());
      }
      // Compute sum - this part identical for two methods
      for (size_t i = 0; i < num_els; ++i) {
        method_2_sum += vec[i];
      }
    }
    double method_2_seconds = timer.GetSeconds();
    // Report results as mean_size, method_1_seconds, method_2_seconds
    std::cout << mean_size << ", " << method_1_seconds << ", " << method_2_seconds;
    // Do something with the dummy sums that cannot be optimized out
    std::cout << ((method_1_sum > method_2_sum) ? "" : " ") << std::endl;
  }

  return 0;
}

我使用的头文件位于此处:

原文由 Apollys supports Monica 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题