我试图声明一个指针并将该指针传递给分配内存的函数。这是一个最小的例子:
#include <string>
#include <iostream>
using namespace std;
void alloc_mem(int &size, double *x);
int main()
{
double *X;
int imax;
alloc_mem(imax, X);
cout << "imax = " << imax << endl;
for (int i = 0; i < imax; i++) {
cout << "X = " << X[i] << endl;
}
delete[]X;
return 0;
}
void alloc_mem(int &size, double *x)
{
size = 10;
x = new double[size];
for (int i = 0; i < size; i++) {
x[i] = (double)i;
}
}
此代码编译,但是当我尝试打印X的值时,我遇到了分段错误。我知道我没有正确地将变量传递给函数,但我不确定如何去做吧。我相信我正在使用x的副本。
此外,编写此代码是为了重现我在更大代码中遇到的问题。
答案 0 :(得分:14)
参数double *x
是函数alloc_mem的局部变量。当函数结束执行时,变量将被销毁。 main中的原始变量X不知道对此参数执行了什么操作,因为它是通过值传递的,该值是函数中使用的副本。
通过指针或引用传递指针。例如
void alloc_mem(int &size, double **x);
void alloc_mem(int &size, double * &x);
void alloc_mem(int &size, double **x)
{
size = 10;
*x = new double [size];
for ( int i = 0; i < size; i++ ) ( *x )[i] = i;
}
void alloc_mem(int &size, double * &x)
{
size = 10;
x = new double [size];
for ( int i = 0; i < size; i++ ) x[i] = i;
}
至于我,我会按以下方式定义函数
double * alloc_mem( int &size )
{
size = 10;
x = new double [size];
for ( int i = 0; i < size; i++ ) x[i] = i;
return x;
}
如果在调用函数之前已知大小,则可以更简单地编写
double * alloc_mem( int size )
{
x = new double [size];
for ( int i = 0; i < size; i++ ) x[i] = i;
return x;
}
考虑到该循环
for ( int i = 0; i < size; i++ ) x[i] = i;
可以代替标准算法std::iota
例如
std::iota( x, x + size, 0.0 );
答案 1 :(得分:4)
用于定义分配函数的标准C ++机制是operator new
。
这就是标准称之为分配函数的原因。
请注意,operator new
与new
- 表达式不同。
new
- 表达式使用相关的分配函数(operator new
函数)来分配内存,然后使用相关的构造函数进行初始化。
但是,在您的情况下,您正在使用(您的命名)分配函数来分配和初始化动态数组。在标准C ++语言设计中,分配和初始化是完全独立的职责,这是非常好的理由,遵循该约定是一个好主意。对你的数组使用 std::vector
,如果你真的真的需要自定义分配(非常怀疑你这样做),那么对{{{>>使用自定义分配器 1}}。
具体例子。
替换您当前的代码
std::vector
与
int main () {
// Declaring variables
double* X;
int imax;
// Calling function
alloc_mem(imax,X);
// Printing
cout << "imax = " << imax << endl;
for (int i=0; i<imax; i++) {
cout << "X = " << X[i] << endl;
}
答案 2 :(得分:2)
如果您有输出参数,则可以通过引用或通过指针传递它。
对于您的size
参数,您通过引用传递(因为它是一个out参数)。
另一个参数是double*
,因此要么添加引用:
void alloc_mem(int & size, double* & x) // (1)
或添加另一个指针(即另一个间接级别):
void alloc_mem(int & size, double** x) // (2)
为了保持一致性,因为您对&
使用了引用(size
)技术,我建议将其用于x
(如(1)中所述)
另请注意,在C ++中,您可能只想传递std::vector
,它知道自己的大小,并执行自动清理(感谢其析构函数):
void alloc_mem(std::vector<double> & x)
另请注意,您可能还希望将向量作为返回值返回(简化代码):
std::vector<double> alloc_mem()
代码段:
// Note: the caller must free the memory using delete[].
void alloc_mem(int& size, double*& x) {
size = 10;
x = new double[size];
for (int i = 0; i < size; i++) {
x[i] = i;
}
}
// Note: automatic vector cleanup. No need of manual delete.
std::vector<double> alloc_mem() {
const int size = 10;
std::vector<double> x(size); // size is 0
for (int i = 0; i < size; i++) {
x[i] = i;
}
return x;
}
答案 3 :(得分:0)
我想问一个跟进问题。
我有一个类似的问题,我通过使用来自莫斯科的解决方案Vlad来解决这个问题:将分配函数内创建的指针返回给变量声明。
一件奇怪的事情是:
如果我按值将数组指针传递给另一个释放内存的函数,比如说
void freearray(int num, double * target)
{
int i;
free(target);
}
免费功能将起作用!无论事实如何,只将target的值传递给函数。
据我所知,即使我只将指针的值传递给分配函数,该值(它是一个内存地址)也应该保持不变,并且该内存地址上的任何操作应该在本地之后保持活动状态功能退出。换句话说,malloc函数在该特定地址分配内存,如果我们使用另一个变量访问该地址,我们仍应该看到该分配。
请纠正我。
谢谢!