【问题标题】:How to pass pointer to function and dynamically allocate memory within function C++如何将指针传递给函数并在函数C++中动态分配内存
【发布时间】:2014-06-03 03:11:43
【问题描述】:

我正在尝试声明一个指针并将该指针传递给分配内存的函数。这是一个最小的例子:

#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 的副本进行操作。

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

【问题讨论】:

  • 试试这个原型:void alloc_mem(int &amp;size, double*&amp; x);。否则 x 仅在函数中被修改。
  • 你是在声明指针,不是初始化它。
  • 我会改用std::vector&lt;double&gt;
  • 第一条评论中提到的原型有效。我发誓我昨晚在凌晨 2:00 尝试过。谢谢!
  • 你为什么要实现上面这样的功能(除了好奇)?这种方法非常不安全。我会听 Ivan 并使用 std::vector 代替。

标签: c++ pointers pass-by-reference pass-by-value function-definition


【解决方案1】:

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

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

请注意,operator newnew 表达式不同。

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

但是,在您的情况下,您使用(您命名的)分配函数只是为了分配和初始化一个动态数组。分配和初始化在标准 C++ 语言设计中是完全分开的职责,有很好的理由,遵循该约定将是一个好主意。为您的数组使用 std::vector,如果您真的真的需要自定义分配(您对此非常怀疑),那么为该 std::vector 使用自定义 allocator


具体例子。

替换您当前的代码

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

【讨论】:

  • 我使用迭代方法来编写答案。视力和非常糟糕的笔记本电脑键盘,更不用说不可靠的,有时是蜗牛的速度连接,这对我来说是唯一实用的方法。 :( 但是谢谢!
  • '我使用迭代的方法来写答案' 我也这样做,通常我从写评论开始,注意这将是一个合适的答案,复制它给答案编辑器并发布第一张照片。之后我继续编辑,通常不希望任何人同时更正我的帖子;) ...
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    当你有一个输出参数时,你可以通过引用,或者通过指针来传递它。

    对于您的size 参数,您通过引用传递(因为它是一个输出参数)。

    另一个参数是double*,所以要么添加引用:

    void alloc_mem(int & size, double* & x)  // (1)
    

    或添加另一个指针(即另一个间接级别):

    void alloc_mem(int & size, double** x)   // (2)
    

    为了连贯性,由于您对 size 使用了参考 (&amp;) 技术,我建议也将其用于 x(如 (1) 中所示)。

    另请注意,在 C++ 中,您可能只想传递一个 std::vector,它知道自己的大小,并进行自动 清理(感谢它的析构函数):

    void alloc_mem(std::vector<double> & x)
    

    另请注意,您可能还希望将向量作为返回值返回(简化代码):

    std::vector<double> alloc_mem()
    

    代码sn-ps:

    // 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;    
    }
    

    【讨论】:

      猜你喜欢
      • 2012-07-03
      • 2016-02-09
      • 2018-07-31
      • 1970-01-01
      • 2013-10-30
      • 1970-01-01
      • 1970-01-01
      • 2013-04-28
      • 1970-01-01
      相关资源
      最近更新 更多