return C++ 中的二维数组
return 2D array in C++
我是 C++ 的新手,我在 python 中进行物理模拟,这需要很长时间才能完成,所以我决定切换到 C++,但我不明白如何制作一个函数将 return 一个 2D 数组(或 3D 数组)
#include <iostream>
#include <cmath>
// #include <complex> //
using namespace std;
double** psiinit(int L, int n, double alpha){
double yj[400][400] = {};
for (int j = 0; j < n; j++)
{
double xi[400] = {};
for (int i = 0; i < n; i++)
{
xi[i] = exp(-(pow((i-(L/4)), 2) + (pow((j-(L/4)), 2)))/alpha) / (sqrt(2)*3.14159*alpha);
};
yj[j] = xi;
};
return yj;
}
int main(){
int L = 10;
int n = 400;
int nt = 200*n;
double alpha = 1;
double m = 1;
double hbar = 1;
double x[n] = {};
double y[n] = {};
double t[nt] = {};
double psi[nt][n][n] = {};
psi[0] = psiinit(L, n, alpha);
cout << psi <<endl;
return 0;
}
我一直在寻找答案,但似乎不适合我的问题
谢谢
要么像上面说的那样制作一个包装器,要么使用一个向量的向量。
#include <vector>
#include <iostream>
auto get_2d_array()
{
// use std::vector since it will allocate (the large amount of) data on the heap
// construct a vector of 400 vectors with 400 doubles each
std::vector<std::vector<double>> arr(400, std::vector<double>(400));
arr[100][100] = 3.14;
return arr;
}
int main()
{
auto arr = get_2d_array();
std::cout << arr[100][100];
}
如果您是 c++ 新手,您应该阅读堆和栈的概念以及栈帧。有很多好的资源。
简而言之,当您声明一个 C 风格数组(例如 yj
)时,它是在函数的堆栈帧中创建的,因此一旦退出帧就无法保证它,并且您的程序在引用该 returned 数组时调用未定义的行为。
有3个选项:
- 将数组作为输出参数传递给函数(非常 C 风格,不推荐)。
- 将数组包装在 class 中(就像
std::array
已经为您做的一样),在这种情况下它保留在堆栈中并在 returned 时复制到调用帧, 但它的大小必须在编译时知道。
- 在堆上分配数组并 return 它,在我看来这最适合您的情况。
std::vector
为您做到这一点:
std::vector<std::vector<double>> psiinit(int L, int n, double alpha){
std::vector<std::vector<double>> yj;
for (int j = 0; j < n; j++)
{
std::vector<double> xi;
for (int i = 0; i < n; i++)
{
const int value = exp(-(pow((i-(L/4)), 2) + (pow((j-(L/4)), 2)))/alpha) / (sqrt(2)*3.14159*alpha);
xi.push_back(value);
}
yj.push_back(xi);
}
return yj;
}
如果您关心性能并且所有内部向量的大小都是固定的 N
,那么使用 std::vector<std::array<double, N>>
.
可能会更好
堆分配和返回指针也可以工作...
而不是
double yj[400][400] = {};
做,
double** yj;
yj = new double*[400];
yj[i] = new double[400];
那么,
return yj;
您对数组、指针和 return 值的理解不完整。我无法就此主题为您编写完整的教程,但我建议您继续阅读。
同时,我建议您使用 std::vector
而不是 C 风格的数组,并将您的多维数组视为具有适当索引的一维向量,例如cell = vector[row * cols + col]
像这样:
#include <cmath>
// using std::exp, M_PI, M_SQRT2
#include <vector>
std::vector<double> psiinit(int L, int n, double alpha) {
std::vector<double> yj(n * n);
double div = M_SQRT2 * M_PI * alpha;
for (int j = 0; j < n; j++)
{
double jval = j - L/4;
jval = jval * jval;
for (int i = 0; i < n; i++)
{
double ival = i - L/4;
ival = ival * ival;
yj[j * n + i] = std::exp(-(ival + jval) / alpha) / div;
}
}
return yj;
}
附录:还有专门的库可以更好更快地支持矩阵。例如本征
https://eigen.tuxfamily.org/dox/GettingStarted.html
我是 C++ 的新手,我在 python 中进行物理模拟,这需要很长时间才能完成,所以我决定切换到 C++,但我不明白如何制作一个函数将 return 一个 2D 数组(或 3D 数组)
#include <iostream>
#include <cmath>
// #include <complex> //
using namespace std;
double** psiinit(int L, int n, double alpha){
double yj[400][400] = {};
for (int j = 0; j < n; j++)
{
double xi[400] = {};
for (int i = 0; i < n; i++)
{
xi[i] = exp(-(pow((i-(L/4)), 2) + (pow((j-(L/4)), 2)))/alpha) / (sqrt(2)*3.14159*alpha);
};
yj[j] = xi;
};
return yj;
}
int main(){
int L = 10;
int n = 400;
int nt = 200*n;
double alpha = 1;
double m = 1;
double hbar = 1;
double x[n] = {};
double y[n] = {};
double t[nt] = {};
double psi[nt][n][n] = {};
psi[0] = psiinit(L, n, alpha);
cout << psi <<endl;
return 0;
}
我一直在寻找答案,但似乎不适合我的问题
谢谢
要么像上面说的那样制作一个包装器,要么使用一个向量的向量。
#include <vector>
#include <iostream>
auto get_2d_array()
{
// use std::vector since it will allocate (the large amount of) data on the heap
// construct a vector of 400 vectors with 400 doubles each
std::vector<std::vector<double>> arr(400, std::vector<double>(400));
arr[100][100] = 3.14;
return arr;
}
int main()
{
auto arr = get_2d_array();
std::cout << arr[100][100];
}
如果您是 c++ 新手,您应该阅读堆和栈的概念以及栈帧。有很多好的资源。
简而言之,当您声明一个 C 风格数组(例如 yj
)时,它是在函数的堆栈帧中创建的,因此一旦退出帧就无法保证它,并且您的程序在引用该 returned 数组时调用未定义的行为。
有3个选项:
- 将数组作为输出参数传递给函数(非常 C 风格,不推荐)。
- 将数组包装在 class 中(就像
std::array
已经为您做的一样),在这种情况下它保留在堆栈中并在 returned 时复制到调用帧, 但它的大小必须在编译时知道。 - 在堆上分配数组并 return 它,在我看来这最适合您的情况。
std::vector
为您做到这一点:
std::vector<std::vector<double>> psiinit(int L, int n, double alpha){
std::vector<std::vector<double>> yj;
for (int j = 0; j < n; j++)
{
std::vector<double> xi;
for (int i = 0; i < n; i++)
{
const int value = exp(-(pow((i-(L/4)), 2) + (pow((j-(L/4)), 2)))/alpha) / (sqrt(2)*3.14159*alpha);
xi.push_back(value);
}
yj.push_back(xi);
}
return yj;
}
如果您关心性能并且所有内部向量的大小都是固定的 N
,那么使用 std::vector<std::array<double, N>>
.
堆分配和返回指针也可以工作... 而不是
double yj[400][400] = {};
做,
double** yj;
yj = new double*[400];
yj[i] = new double[400];
那么,
return yj;
您对数组、指针和 return 值的理解不完整。我无法就此主题为您编写完整的教程,但我建议您继续阅读。
同时,我建议您使用 std::vector
而不是 C 风格的数组,并将您的多维数组视为具有适当索引的一维向量,例如cell = vector[row * cols + col]
像这样:
#include <cmath>
// using std::exp, M_PI, M_SQRT2
#include <vector>
std::vector<double> psiinit(int L, int n, double alpha) {
std::vector<double> yj(n * n);
double div = M_SQRT2 * M_PI * alpha;
for (int j = 0; j < n; j++)
{
double jval = j - L/4;
jval = jval * jval;
for (int i = 0; i < n; i++)
{
double ival = i - L/4;
ival = ival * ival;
yj[j * n + i] = std::exp(-(ival + jval) / alpha) / div;
}
}
return yj;
}
附录:还有专门的库可以更好更快地支持矩阵。例如本征 https://eigen.tuxfamily.org/dox/GettingStarted.html