【问题标题】:Matlab's reshape in c++Matlab在C++中重塑
【发布时间】:2014-06-01 15:53:15
【问题描述】:

在 Matlab 中,只要元素的数量不变,就可以将(N 维)矩阵从任何维度“重塑”到任何其他维度。那就是:

A = rand(10,10);
B = reshape(A, 100, 1);

Matlab 可以非常有效地做到这一点,因为 A 和 B 仍然指向同一块 100 个双精度数据块,它们只有在写入 A 或 B 时才会被复制:这称为写时复制。

我想要 C/C++ 中的这个 reshape 功能,也就是我希望能够做到这一点:

double flat[100];
double square[10][10] = ... flat ...;

这样正方形代表相同的数据,但解释器以另一种方式索引。

最后,我想要的是语法糖,做 square[i][j] 而不是 square[10*i+j]。所以,是的,编写一些能够以不同维度共享数据的类(如 matlab 所做的那样)重载索引运算符可能会做到这一点。不过,我正在寻找更简单的解决方案。

另一方面,我担心 C++ 标准允许编译器以不同的方式实现维度数组,这不符合我的要求。例如 int[10][10] 可以实现为 10 个双精度块上的 10 个块和指向它们的 10 个双精度指针块。而且,我可以自己创造这样的东西:

double **blowUp(double *array, int m, int n) {
    double **r = new double[m];
    for(int i=0; i<m; ++i, array+=n) r[i] = array;
    return r;
}

但是语法糖的想法消失了一点,特别是因为我还需要清理包装器数组。

另一种解决方案可能是模板下标运算符重载,其中模板参数包含数据的第一维:

http://ideone.com/aonHN2

但是正如编译错误所暗示的那样,如果不将数据包装在类结构中,这是不可行的。那么,如果我想要我想要的东西,我是否注定要在一个类中包装数据并编写大量样板代码?请让我知道你的想法!

【问题讨论】:

  • 你知道编译时reshape的尺寸吗?
  • 所以基本上,你懒得写课了? :)
  • @RodyOldenhuis 我不喜欢样板代码。所以,也许我太懒了,写了一个搞砸了我的代码的类,但我并没有懒得在 SO 上构建一个问题,让我找到更合适的解决方案。
  • @DavidHeffernan 我可以对它们进行硬编码,因为我正在处理所有尺寸为 1600x1200 的图像,但我会发现这是一种令人失望的方法。所以我猜不是,你的建议是什么?
  • 如果您不想对尺寸进行硬编码,为什么要接受您所做的答案?

标签: c++ c arrays matlab reshape


【解决方案1】:

如果您使用的是简单数组,则使用reinterpret_cast 非常容易。以你为例:

#include <iostream>

int main()
{
    int flat[100];
    for (int i=0; i<100; ++i)
        flat[i]=i;
    // now reinterpret that flat array as a 10x10 square
    int (&square)[10][10] = *reinterpret_cast<int(*)[10][10]>(flat);
    // print an arbitrary row
    for (int i=0; i<10; ++i)
        std::cout << square[5][i] << ' ';
    std::cout << '\n';
}

这个简单的程序打印:

50 51 52 53 54 55 56 57 58 59 

【讨论】:

  • 这与我的预期完全相反,因为我预期没有优雅的解决方案,但正是我正在寻找的。非常感谢!
  • 这需要在编译时知道尺寸。
【解决方案2】:

最简洁的方法是将平面数组包装在一个类中。您可以实现使用 operator[] 来返回指向第 ith 行的指针。这个operator[] 的实现需要知道你希望对底层数组施加的形状。

【讨论】:

    猜你喜欢
    • 2013-08-09
    • 2016-01-11
    • 1970-01-01
    • 2017-12-25
    • 2016-04-22
    • 2012-08-07
    • 1970-01-01
    相关资源
    最近更新 更多