【问题标题】:quick way of resizing vector of vectors to correct size (c++)将向量的向量调整为正确大小的快速方法(c ++)
【发布时间】:2015-10-23 02:00:35
【问题描述】:

我想尽可能高效地将 std::vector > 调整为已知大小(m,n),理想情况下不进行任何内存复制(T 是浮点数或双精度数)。

class Foo {
    std::vector< std::vector< T > > data;
    std::vector< std::vector< T > > data_norm;

    std::vector< T > min_values;
    std::vector< T > max_values;

    void normalize();
}

data 是动态填充的,一次将新数据推回一个“行”。保证每个“行”具有相同数量的元素。所以它实际上是一个 m x n 表。

然后在某一时刻我调用 normalize() 方法:

  • 扫描数据
  • 找到每个的最小/最大值并将它们写入min_valuesmax_values
  • 将每个元素标准化为该列的最小值/最大值并存储在 data_norm

目前我在 normalize() 方法的开头执行 data_norm = data 只是为了确保将 data_norm 分配给大小合适,没有进一步的重新分配。但这涉及复制所有内存。没有这个内存副本有没有办法做到这一点?

我看过 this 的帖子,提示

std::vector<std::vector<T>> my_vec(m, std::vector<T>(n))

但是在我的情况下 my_vec 已经存在。我可以创建并分配一个 new_vec

std::vector<std::vector<T>> new_vec(m, std::vector<T>(n));
data_norm = new_vec;

但我想这仍然会有内存副本,实际上它会比 data_norm = data 慢,因为初始化了一个全新的向量 (new_vec)并分配,我已经有一个大小合适的源向量。

我希望有一种方法可以通过类似调整大小的方法来做到这一点?但是如果没有迭代并调整每个子向量的大小 - 我猜这会产生疯狂的重新分配。

【问题讨论】:

  • 你的问题是初始化,但是在你发帖的最后,你说 my_vec 已经存在,所以这并不是真正的向量初始化,而是调整向量的大小。
  • 如果效率是首要考虑因素,我会避免使用std::vector,为m x n 大小的一维数组分配内存,并提供方便的函数来访问数据。
  • @RSahu Boost 有一个类可以让这一切变得简单:boost.org/doc/libs/1_55_0/libs/multi_array/doc/user.html

标签: c++ optimization vector


【解决方案1】:

您可以使用vector::resize(),它不会创建临时向量

http://www.cplusplus.com/reference/vector/vector/resize/

// resizing vector
#include <iostream>
#include <vector>

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

  // set some initial content:
  for (int i=1;i<10;i++) myvector.push_back(i);

  myvector.resize(5);
  myvector.resize(8,100);
  myvector.resize(12);

  std::cout << "myvector contains:";
  for (int i=0;i<myvector.size();i++)
    std::cout << ' ' << myvector[i];
  std::cout << '\n';

  return 0;
}

输出:

myvector contains: 1 2 3 4 5 100 100 100 0 0 0 0

【讨论】:

  • 哇,谢谢。我没有意识到第二个参数会这样应用。
【解决方案2】:

目前我在我的 normalize() 方法开始时执行 data_norm = data 只是为了确保 data_norm 分配到正确的大小并且没有进一步的重新分配。

首先,您应该简单地设计您的程序,使任何人都无法调整向量的大小,并确保您不会调整它们的大小,然后您就可以完全避免这项工作。如果你想更加安全,你可以在你的代码中加入一些断言来确保大小在调试模式下永远不会改变。

此外,如果您想“尽可能高效地”完成这项工作,那么您应该避免使用向量的向量,因为对于矩形矩阵来说,分配比必要的要多。

目前没有标准容器可以提供具有运行时边界的高效多维数组,但您可以很容易地定义一个。这是一个非常简单的示例。

template<typename T>
class vector2d {
  std::vector<T> data;
  int columns;

public:
  struct index { int r, c; };

  vector2d(index i) : data(i.r * i.c), columns(i.c) {}
  T &operator[] (index i) { return data[i.r*columns + i.c]; }
}

然后你可以写:

class Foo {
    vector2d<T> data;
    vector2d<T> data_norm;

    std::vector<T> min_values;
    std::vector<T> max_values;

    void normalize();

    Foo(int n, int m) : data({n, m}), data_norm({n, m}) {}
}

如果您也想对任意数量的维度 that can be done 执行相同的操作。

【讨论】:

  • 感谢您。我的数据是动态的,所以我不能设计程序来不允许调整向量的大小。不过,2d->1d 包装器是个好主意。
  • @memo 好吧,无论您对调整矩阵大小有什么要求,您都应该能够确保它在设计上始终是正确的大小,而不是在您碰巧注意到它不正确时依赖于按需调整大小大小。
猜你喜欢
  • 2021-04-09
  • 1970-01-01
  • 2021-01-30
  • 2018-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-20
相关资源
最近更新 更多