我是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);
}
它也可以完美运行,并且不使用双指针。为什么在一种情况下需要双指针,而在另一种情况下不需要?
如果您需要更多信息,请询问。我没有提供完整的第一个代码,为了更好地概述,如果我错过了重要的部分,我将发布其余的代码。
使用第二个函数实现会调用未定义的行为。
它只是发生了这样的情况:被调用的函数
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;