使用realloc操作数组时双指针的必要性

问题描述 投票:0回答:1

我是C++编程新手,想尝试手动内存管理(我知道建议不要使用手动内存管理,但我仍然想尝试一下)。

我的目标是编写一个函数,可以使用

realloc
将元素追加到数组中。

我用这个

struct
:

struct pathToCity{  
  int lengthCities;
  char cities[100];
};

这是我的功能:

void appendToPathToCitiesArray(pathToCity **array, int *length, pathToCity newCity) {
  if (*length == 0) {
    *array = (pathToCity*) malloc(sizeof(pathToCity));
  }
  else {
    *array = (pathToCity*) realloc(*array, (*length + 1) * sizeof(pathToCity));
  }
  if (array == NULL) {
    cout << "Error allocating memory." << endl;
    exit(-1);
  }
  (*array)[*length] = newCity;
  (*length)++;
}

这里我定义了一个数组:

int lengthQueue = 0;
    pathToCity *queue;

这里我实例化了我的

struct
的一个实例:

pathToCity newPath = {0, ""};

最后我使用我的功能:

appendToPathToCitiesArray(&queue, &lengthQueue, newPath);

该函数工作正常,因为它使用双指针。根据我的研究(不幸的是我找不到解释这一点的 stackoverflow 帖子),这里的双指针是必要的,因为一旦指针传递给函数,就不可能更改函数内部的指针。因此,一旦我想使用

realloc
来更新我的数组,就需要双指针。

但我也在不同的文件中尝试过:

#include <iostream>


using namespace std;



struct shortText {
    int lengthText;
    char text[3];
};


void append(shortText *array, int *length, shortText newCity) {
  if (*length == 0) {
    array = (shortText*) malloc(sizeof(shortText));
  }
  else {
    array = (shortText*) realloc(array, (*length + 1) * sizeof(shortText));
  }
  if (array == NULL) {
    cout << "Error allocating memory" << endl;
    exit(-1);
  }
  array[*length] = newCity;
  (*length)++;
}


int main() {

  int length = 3;
  shortText *arr = (shortText*) malloc(sizeof(shortText) * length);
  
  arr[0] = {2, "ab"};
  arr[1] = {2, "ab"};
  arr[2] = {2, "ab"};

  shortText s = {2, "ab"};
  append(arr, &length, s);

  arr[3] = {8, "ji"};

  cout << length << endl;
  cout << arr[3].lengthText << endl;





  free(arr);
}

它也可以完美运行,并且不使用双指针。为什么在一种情况下需要双指针,而在另一种情况下不需要?

如果您需要更多信息,请询问。我没有提供完整的第一个代码,为了更好地概述,如果我错过了重要的部分,我将发布其余的代码。

c++ function realloc pointer-to-pointer
1个回答
2
投票

使用第二个函数实现会调用未定义的行为。

它只是发生了这样的情况:被调用的函数

realloc
没有改变指针
arr
中存储的地址。该函数只是扩大了内存的初始范围。但一般来说它可以在不同的地址分配另一个内存范围。在这种情况下,在
arr
中声明的指针
main
将无效。

您需要传递一个指针到指针,因为取消引用指针到指针,您可以直接访问原始指针

arr
,从而可以在函数内更改它。否则,该函数将处理原始指针值的副本,并且更改副本不会影响原始指针。

就是所谓的C含义中的pass by引用。

比较这两个演示程序。

#include <iostream>

typedef int T;

void f( T x )
{
    x = T();
}

int main()
{
    T x = 10;

     std::cout << "Before calling f() x = " << x << '\n';

     f( x );

     std::cout << "After  calling f() x = " << x << '\n';
}

#include <iostream>

typedef int T;

void f( T *x )
{
    *x = T();
}

int main()
{
    T x = 10;

     std::cout << "Before calling f() x = " << x << '\n';

     f( &x );

     std::cout << "After  calling f() x = " << x << '\n';
}

特意使用了typedef

typedef int T;

为了表明除了类型

int
之外,还可以使用指针类型,例如
int *

typedef int * T;

只在 main 中你应该写

int value;
T x = &value;

并在两个演示程序中调用函数

f

在 C++ 中,你可以像这样通过引用传递指针

void append(shortText * &array, int &length, shortText newCity);

注意这个realloc的调用

array = (shortText*) realloc(array, (*length + 1) * sizeof(shortText));

是不安全的,如果函数无法分配新的内存范围并返回空指针,则可能导致内存泄漏。例如,您应该使用中间指针

shortText *tmp = (shortText*) realloc(array, (*length + 1) * sizeof(shortText));

if ( tmp != nullptr ) array = tmp;
© www.soinside.com 2019 - 2024. All rights reserved.