C++指针/for 循环混淆

C++ pointer/for-loop confusion

本文关键字:循环 for 指针 C++      更新时间:2023-10-16

我正在尝试编写一个程序,该程序使用指针从 cin 读取值,然后输出值及其在数组中的位置。我不知道为什么printNumbers1有效,但printNumbers2不起作用。这是程序(底部附近的相关代码):

#include <iostream>
using namespace std;
int *readNumbers(int);
void printNumbers1(int*);
void printNumbers2(int*);
int main()
{
int *numbers = readNumbers(5);
printNumbers1(numbers);
printNumbers2(numbers);
return 0;
}
int *readNumbers(int n)
{
int a[n];
int *numbers;
numbers = &a[0];
for (int i=0; i<n; i++)
{
cin >> *(numbers+i);
}
return numbers;
}
void printNumbers1(int *numbers)
{
cout << 0 << ' ' << *(numbers) << endl
<< 1 << ' ' << *(numbers+1) << endl
<< 2 << ' ' << *(numbers+2) << endl
<< 3 << ' ' << *(numbers+3) << endl
<< 4 << ' ' << *(numbers+4) << endl;
}
void printNumbers2(int *numbers)
{
for (int i=0; i<5; i++)
{
cout << i << ' ' << *(numbers+i) << endl;
}
}

当我运行该程序时,它按预期为 printNumbers1 工作,但为 printNumbers2 输出看似随机的数字和 0 的组合。我觉得两个 printNumbers 函数应该功能相同,但它们没有。我错过了什么?

发生这种情况是由于两件事的组合:

  • C++ 不允许可变长度数组- 这是一个流行的扩展,但声明int a[n]不是标准的。
  • 您不能从函数返回指向局部变量的指针-readNumbers内部的指针numbers指向局部变量a一个局部变量。您可以在函数内部使用此指针,但在函数外部,它变得无效,因为a超出范围。

使用超出范围的变量会导致未定义的行为。这个问答很好地解释了正在发生的事情,以及为什么它看起来程序运行良好。

如果要使用内置指针,请删除int a[n],并更改numbers的声明,如下所示:

int *numbers = new int[n];

您还需要添加

delete[] numbers;

return 0行之前,以避免内存泄漏。

我假设您编写此代码是作为学习练习的一部分。不过,一般来说,C++中更好的方法是使用std::vector<int>,它从代码中隐藏指针操作,并为您处理资源管理。

readNumbers 返回指向具有自动存储持续时间的变量的指针。

取消引用该指针的行为是未定义的。

请改用 std::vector。依靠返回值优化来避免任何多余的价值副本。

在这里,您已经在函数内部创建了数组 a[n],因此它是一个局部变量,因此在函数范围结束后,可能会也可能不会删除此数组。切勿在函数之外使用局部变量的地址。此代码正在工作:

#include <iostream>
using namespace std;
int *readNumbers(int);
void printNumbers1(int*);
void printNumbers2(int*);
int main()
{
int *numbers = readNumbers(5);
printNumbers1(numbers);
printNumbers2(numbers);
return 0;
}
int *numbers;
int *readNumbers(int n)
{
numbers = new int[n];
for (int i=0; i<n; i++)
{
cin >> *(numbers+i);
}
return numbers;
}
void printNumbers1(int *numbers)
{ 
cout << 0 << ' ' << *(numbers) << endl
<< 1 << ' ' << *(numbers+1) << endl
<< 2 << ' ' << *(numbers+2) << endl
<< 3 << ' ' << *(numbers+3) << endl
<< 4 << ' ' << *(numbers+4) << endl;
}
void printNumbers2(int *numbers)
{
for (int i=0; i<5; i++)
{
cout << i << ' ' << *(numbers+i) << endl;
}
}