如何将指针传递给函数,并在函数C++中动态分配内存

How to pass pointer to function and dynamically allocate memory within function C++

本文关键字:函数 C++ 内存 动态分配 指针      更新时间:2023-10-16

我试图声明一个指针,并将该指针传递给分配内存的函数。这里有一个最小的例子:

#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的副本。

此外,编写此代码是为了在更大的代码中重现我遇到的问题。

参数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 );

定义分配函数的标准C++机制是operator new

这就是标准将其称为分配函数的原因。

注意,operator new不同于new-表达式。

new表达式使用相关的分配函数(operator new函数)来分配内存,然后使用相关的构造函数进行初始化。

然而,在您的情况下,您使用(命名的)分配函数只是分配和初始化一个动态数组。在标准C++语言设计中,分配和初始化是完全分开的职责,这是有充分理由的,遵循这一约定是个好主意。对您的数组使用std::vector,如果您确实确实需要自定义分配(对此非常怀疑),则对该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;
}

带有

#include <vector>
int main() {
    int const imax = whatever();
    std::vector<double> X( imax );
    cout << "imax = " << imax << endl;
    for (int i=0; i<imax; i++) {
       X[i] = i;  // If you really want these values in the vector.
       cout << "X = " << X[i] << endl;
    }
}

当您有输出参数时,您可以通过引用或通过指针传递它。

对于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;    
}