我正在处理涉及字符串指针的作业。有两个功能。第一个输入字符串数组,将每个元素的地址放入单独的数组,然后将指针返回到该数组。第二个函数获取返回的指针,并仅使用指针打印出原始数组的元素。但是,当我测试它时,每个指针中被取消引用的字符串** ptrToPtr是不同的。我想知道为什么
这是功能1:
string** arrayOfPtrs(string arr[], int size)
{
string* ptrArray; //The array of string pointers
string** ptrToPtr; //A pointer to the array of string pointers
ptrArray = new string[size];
//ptrArray = arr;
int i = 0;
while (i < size)
{
ptrArray = &arr[i];
i++;
ptrArray++;
}
ptrToPtr = &ptrArray;
return ptrToPtr;
}
这是功能2:
void outputArray(string** arr, int size)
{
int count = size; //An int variable that stores the size of array
string* ptr = *arr; //A pointer that stores the address to the last element
//in the string pointer array
while (count > 0)
{
cout << *(ptr - count) << " ";
count--;
}
cout << endl;
}
这是main()的一部分:
string strArr[] = { "echo", "charlie", "delta", "bravo", "delta" };
string** strPtrs;
strPtrs = arrayOfPtrs(strArr, 5);
cout << "Actual results: ";
outputArray(arrayOfPtrs(strArr, 5), 5);
cout << endl << endl;
我在哪里出错?还是有更好的方法将指针指向字符串指针?
这是一个完全在main中运行的类似程序:
int main()
{
string words[30];
string* s;
s = new string[30];
string** t;
createArray(30, words);
int num = 0;
t = &s;
while (num < 30)
{
s = &words[num];
num++;
s++;
}
string* u = *t;
int j = 30;
for (int i = 0; i < 30; i++)
{
cout << "*(s - " << j << ") - " << *(s - j) << endl;
cout << "words[ " << i << " ] - " << words[i] << endl;
cout << "*(u - " << j << " ) - " << *(u - j) << endl << endl;
j--;
}
}
该程序运行完美。有什么想法吗?
答案 0 :(得分:0)
这是不正确的:
while (i < size)
{
ptrArray = &arr[i];
i++;
ptrArray++;
}
将ptrArray = &arr[i];
替换为*ptrArray = arr[i];
。就目前而言,您每次遍历循环都只是覆盖相同的指针,而永远不会做任何有用的事情。
这也不正确:
string* ptrArray; //The array of string pointers
// ...
ptrToPtr = &ptrArray;
return ptrToPtr;
一旦return
,它就会晃来晃去。一旦它们超出范围,就不允许使用指向局部(堆栈)变量的指针。
答案 1 :(得分:0)
首先,我发现您的设置中存在一些问题
string* ptrArray = new ...
现在,您有了一个字符串数组(数组在语义上等同于指向第一个元素的指针)。但是,您需要一个字符串指针数组。因此,您需要string** ptrArray = new ...
,并且此错误级联到其余函数。
您永远不会删除使用 new 分配的数组。这导致内存无法释放。您需要在最后一个代码段中delete[] *strPtrs;
释放您在方法中分配的内存。通常,最好是让负责分配内存的人负责地释放它。我在下面为您展示了另一个解决方案。
最后:
string* ptrArray; //The array of string pointers
string** ptrToPtr; //A pointer to the array of string pointers
ptrToPtr指向ptrArray,这是一个局部变量。离开该函数时它将变为无效,因此取消引用返回的指针将是不确定的行为。
某些标准库(例如cstdio的snprintf)使用一种通用方法,因此调用方负责分配和释放:
void arrayOfPtrs(string arr[], int size,/*new param*/ string** outArray)
{
string** iter = outArray; // Iterator pointer
int i = 0;
while (i < size)
{
*iter = &arr[i];
i++;
iter++;
}
}
这里发生的是,调用者为函数提供了一个指向指针的指针(它指向第一个指针)。请注意,指针可以与索引运算符等一起用作数组。因此,实际上它是指针数组。然后,通过增加复制的指针使其填充,使其从指针元素跳到指针元素。实际存储数组的位置不是此函数的问题。
像这样使用它:
// Variant 1: Use local variable if size is constant
string* arr[5];
arrayOfPtrs(strArr, 5, arr);
std::cout << *arr[0]; // Dereferences a pointer in arr to get the string which is actually in strArr
// Variant 2: Allocate heap memory (if you need dynamic size)
int size ...; // From somewhere
string** arr = new string[size];
arrayOfPtrs(strArr, size, arr);
std::cout << *arr[0]; // Same again
... // Do further work
delete[] arr; // Free memory
因此,在调用函数之前,必须先分配内存(或使用局部变量),然后再将其传递给函数。在双指针中,第一个*
用于表示“指向字符串的指针”的数据类型,第二个将其指定为“指针数组”。