更有效地访问std :: vector

时间:2016-02-20 09:23:33

标签: c++ performance vector

在我的项目中,我正在定义一个类Matrix,我使用的数据结构是std::vector<std::vector<T> > matrix;

现在我的问题是:如何更有效地访问它?如果我没记错的话,通过索引(例如matrix [i] [j])访问是效率杀手,而建议的方式是通过迭代器。这是对的吗?

假设它是,那么我有另一个问题:有时我需要知道我正在操作的行或列的索引。例如,考虑逐个元素添加另一个矩阵:我怎么能说

C[i][j] = A[i][j] + B[i][j]

不使用两个索引ij?然后我有其他操作,比如乘Vector(我定义的另一个类),但我想如果我正确理解访问元素的最有效方法,那么我可以复制相同的模式。

3 个答案:

答案 0 :(得分:1)

  

如何更有效地访问它?如果我没记错的话,通过索引(例如matrix [i] [j])访问是效率杀手,而建议的方式是通过迭代器。这是对的吗?

不要猜,读起来:

  

<强>复杂性

     

的常数。

     

http://en.cppreference.com/w/cpp/container/vector/operator_at

正如哈罗德所指出的,这并不意味着它有效率,但知道这个算子(总是?)实现类似于...

// data member
T * underlying_array;
// in operator[]
return *(underlying_array + position); // underlying_array[position]

......这将是相对较好的,表现明智。虽然请注意我也听说过STL实现会向operator[]添加一个边界检查,这会增加一个分支,从而可能会对性能产生负面影响。

也就是说,您当然可以更改代码以使用迭代器而不是operator[],例如:

std::vector<std::vector<T>> A,B,C;
// Check for correct sizes first!
auto a_row = std::begin(A);
auto c_row = std::begin(C);
auto b_row = std::begin(B);
for (; a_row != std::end(A); ++a_row, ++b_row, ++c_row) {
  // Check correct sizes!
  auto a_col = std::begin(*a_row);
  auto b_col = std::begin(*b_row);
  auto c_col = std::begin(*c_row);
  for (; a_col != std::end(*a_row); ++a_col, ++b_col, ++c_col) {
    *c_col = *a_col + *b_col;
  }
}

可以更有效......但是否值得...

真正的性能杀手如果您的数据并非全部连续存储。 std::vector将它的元素存储在连续的内存中,但是将std::vector s(作为“外部”向量)连续存储并没有帮助你,因为“内部”向量可能将它们的数据存储在不同的位置。因此,为了将矩阵的所有数据保存在连续的内存中,您应该使用单个std::vector并自己进行正确的列 - 行索引(您的矩阵可以提供operator[]返回对实例的引用辅助类反过来实现其operator[]来访问矩阵,使matrix[1][2]之类的调用成为可能。)

答案 1 :(得分:0)

来自std :: vector

的文档
  

元素连续存储,这意味着元素可以   不仅可以通过迭代器访问,还可以使用常规的偏移量   指向元素的指针。

因此,它应该类似于从数组访问,这应该是有效的。

此外,向量中元素的随机访问是常量,不依赖于向量的大小。 O(1)。您也可以使用它来获取向量的基础数组并访问它,但这应该与使用随机访问相同..

int main()
{
   std::vector<std::vector<int>> matrix;

   matrix.push_back({1,2,3});
   matrix.push_back({1,2,3});
   matrix.push_back({1,2,3});

   int op = matrix.data()[0][0] + matrix.data()[0][1];

   std::cout << "OP should be 3 : Real op" << op << std::endl;

}

答案 2 :(得分:0)

  

在我的项目中,我正在定义一个类Matrix和数据结构   我使用的是std::vector<std::vector<T> > matrix;

     

现在我的问题是:如何更有效地访问它?

测量当前速度并在修改代码后再次测量。这将告诉您是否有任何可衡量的改进。

您可以尝试通过将数据存储为大小宽度x高度的简单std::vector<T>来提高性能,并在给定x和y时相应地计算偏移量

例如(只是为了了解概念,没有错误检查或任何事情):

// ...

private:
    int width;
    std::vector<T> v;

// ...

public:

    Matrix(int width, int height) : width(width), v(width * height)
    {
    }

    T get(int x, int y) const
    {
        return v[(y * width) + x];
    }

// ...

但是很可能你的机器太快了,你的数据太小而看不出任何差异。