我是C ++的新手,来自Fortran 90+和MATLAB背景。我一直在玩C ++中的指针,我偶然发现了一些我无法解释的内容。对谷歌和Stack Overflow的搜索并没有真正产生解释。
这是我提出的一个任意例子,只是乱搞,试图理解C ++是如何工作的。
本质上,我要做的是在函数内分配动态数组,填充数组,并在调用函数中返回指向数组的指针。如果我使用void函数返回指向数组的指针,则它不起作用。如果我将它作为带返回的正常函数来执行,它就可以正常工作。我们分别称之为案例1和案例2。
我汇总了一个我的意思的例子:
#include <iostream>
using namespace std;
// Prototypes
void populate(int rows, int cols, double* ptr_to_mat);
double* populate_return(const int rows, const int cols);
// Main function
int main()
{
int rows, cols;
cout << "Number of rows: ";
cin >> rows;
cout << "Number of columns: ";
cin >> cols;
cout << endl;
double* ptr_to_mat;
populate(rows, cols, ptr_to_mat);
cout << endl << "OUTPUT IN main FROM populate" << endl;
for (int r = 0; r <= rows-1; r++)
for (int c = 0; c <= cols-1; c++)
cout << "mat(" << r << "," << c << ") = " << ptr_to_mat[c+cols*r] << endl;
cout << endl << endl;
ptr_to_mat = populate_return(rows, cols);
cout << endl << "OUTPUT IN main FROM populate_return" << endl;
for (int r = 0; r <= rows-1; r++)
for (int c = 0; c <= cols-1; c++)
cout << "mat(" << r << "," << c << ") = " << ptr_to_mat[c+cols*r] << endl;
delete [] ptr_to_mat;
return 0;
}
// Other functions
// Return pointer by modifying argument -- CASE 1
void populate(const int rows, const int cols, double* ptr_to_mat)
{
double* internal_mat = new double[rows*cols];
cout << "INPUT IN populate" << endl;
for (int r = 0; r <= rows - 1; r++)
for (int c = 0; c <= cols - 1; c++)
{
cout << "mat(" << r << "," << c << ") = ";
cin >> internal_mat[c+cols*r];
}
ptr_to_mat = internal_mat;
cout << endl << "OUTPUT IN populate" << endl;
for (int r = 0; r <= rows-1; r++)
for (int c = 0; c <= cols-1; c++)
cout << "mat(" << r << "," << c << ") = " << ptr_to_mat[c+cols*r] << endl;
}
// Return pointer using "return" -- CASE 2
double* populate_return(const int rows, const int cols)
{
double* internal_mat = new double[rows*cols];
cout << "INPUT IN populate_return" << endl;
for (int r = 0; r <= rows - 1; r++)
for (int c = 0; c <= cols - 1; c++)
{
cout << "mat(" << r << "," << c << ") = ";
cin >> internal_mat[c+cols*r];
}
cout << endl << "OUTPUT IN populate_return" << endl;
for (int r = 0; r <= rows-1; r++)
for (int c = 0; c <= cols-1; c++)
cout << "mat(" << r << "," << c << ") = " << internal_mat[c+cols*r] << endl;
return internal_mat;
}
运行上述代码的结果如下:
Number of rows: 3
Number of columns: 2
CASE 1
INPUT IN populate
mat(0,0) = 1
mat(0,1) = 2
mat(1,0) = 3
mat(1,1) = 4
mat(2,0) = 5
mat(2,1) = 6
OUTPUT IN populate
mat(0,0) = 1
mat(0,1) = 2
mat(1,0) = 3
mat(1,1) = 4
mat(2,0) = 5
mat(2,1) = 6
OUTPUT IN main FROM populate
mat(0,0) = -1.72952e-41
mat(0,1) = -2.77962e-42
mat(1,0) = -2.77966e-42
mat(1,1) = -2.7797e-42
mat(2,0) = -6.02988e-42
mat(2,1) = -2.77979e-42
CASE 2
INPUT IN populate_return
mat(0,0) = 1
mat(0,1) = 2
mat(1,0) = 3
mat(1,1) = 4
mat(2,0) = 5
mat(2,1) = 6
OUTPUT IN populate_return
mat(0,0) = 1
mat(0,1) = 2
mat(1,0) = 3
mat(1,1) = 4
mat(2,0) = 5
mat(2,1) = 6
OUTPUT IN main FROM populate_return
mat(0,0) = 1
mat(0,1) = 2
mat(1,0) = 3
mat(1,1) = 4
mat(2,0) = 5
mat(2,1) = 6
我的假设是它与调用函数中指定指针的时间有关。因此,在情况2中,在函数内的信息从内存中释放之前,它被分配到左侧,而在情况1中,在调用函数中指定指针之前释放该内存,因为赋值发生在右手边。
这听起来有道理吗?如果没有,案例2的工作原因是什么,但案例1没有?
如果我想在函数中分配多个动态数组并返回指向这些数组的指针,我必须使用void函数。在那种情况下可以/应该做什么?
答案 0 :(得分:4)
void
版本不起作用的原因是指针参数是按值传递的,因此该函数有自己的副本。要使其“工作”,您必须传递对指针的引用:
void populate(int rows, int cols, double*& ptr_to_mat);
// ^
请注意,在实际代码中,您倾向于使用std::vector
或管理其自身资源的其他类型,而不是将资源管理留给调用者。例如,
#include <vector>
std::vector<double> populate(int rows, int cols);
答案 1 :(得分:0)
在c ++中,参数是按值传递的,因此在第一个实例中,您要修改结果指针的副本。使用指向指针的指针,并通过引用它来设置结果。
或者作为更好的答案建议:使用参考。这不是c!
答案 2 :(得分:0)
要在void
功能中正确设置指针,您需要通过引用传递它:
void populate(const int rows, const int cols, double*& ptr_to_mat) { // ...