函数中的局部C++指针

C++ pointers local in functions

本文关键字:C++ 指针 局部 函数      更新时间:2023-10-16

这是我在C++中为学习目的创建的代码片段,我目前正在尝试自学。我的问题是:

为什么*ptr = 30会更改main中最后两个cout语句的输出值?(输出为30、30、30)。因此,为什么int y = 30;ptr = &y;不更改main中的输出,并保留在函数的本地?(如果我注释掉*ptr=30,而不是前两个语句,则输出为30,5,5)

如果我将函数输入更改为void printPointer(int *&fptr),并仅注释出*ptr = 30,那么我的main中的*ptr将被修改,而不是x。我理解这一点,因为pass-by-reference是在修改指针,而不是我的第一条语句如何修改main中的*ptr和x。

#include <iostream>
using namespace std;
void printPointer(int *fptr);
int main()
{
    int x = 5;
    int *ptr = &x;
    printPointer(ptr);
    cout << *ptr << endl;
    cout << x << endl;
    return 0;
}
void printPointer(int *fptr)
{
//  int y = 30;             // this does not change the output of the last two couts in main, output = 30, 5, 5
 // fptr = &y;
    *fptr = 30;          // uncommenting this and commenting out the former two statements: output = 30, 30, 30
    cout <<  *fptr << endl;
}

*ptr = 30更改所指向的值。在您的案例中,您已经将ptr设置为指向x(当您执行ptr = &x并将其作为参数传递给printPointer()时)。因此x的值发生了变化。

当您改为执行int y = 30; fptr = &y;时,您所要做的只是将fptr更改为指向不同的变量。就是这样。你不会改变所指向的值(即x的值)。您不会影响ptr,因为fptr是一个单独的局部变量。所以ptr仍然指向x,而x仍然是5。

当您修改函数以引用指针时,将fptr更改为指向y也会更改ptr,因为它们是相同的变量。

*fptr = 30将取消引用存储在fptr中的地址,并在内存中的位置写入30。您在内存中给printPointer(ptr)函数的这个地址。在本例中,ptr是x的地址,您使用ptr = &x将其分配给ptr。

int y= y声明了函数的局部变量。fptr = &y将y的地址分配给fptr(并覆盖ptr中的值)。因此,在这种情况下的最后一行将更改局部变量y而不是x。

如果我理解正确,您询问的是两段代码。第一个是你发布的:

#include <iostream>
using std::cout;
void f(int* fptr) {
    *fptr = 30;  // 11
    cout << "*fptr = " << *fptr << 'n'; // 12
}
int main() {
    int x = 5; // 1
    int* ptr = &x; // 2
    f(ptr); // 21
    cout << "*ptr = " << *ptr << 'n'; // 22
    cout << "x = " << x << 'n'; // 23
}

在这种情况下,指针总是指向x,在函数中,您仍然可以更改x的值,因为这就是fptr所指向的。如果有帮助的话,下面演示每行末尾的变量值:NE表示变量当前不存在。

1.  x = 5, ptr = NE, fptr = NE
2.  x = 5, ptr = &x, fptr = NE
11. x = 30, ptr = &x, fptr = &x
12. x = 30, ptr = &x, fptr = &x
21. x = 30, ptr = &x, fptr = NE

在那之后,值不会改变,并且所有三个语句都将打印30。

第二个是:

#include <iostream>
using std::cout;
void f(int*& fptr) {
    int y = 30; // 11
    fptr = &y; // 12
    cout << "*fptr = " << *fptr << 'n'; // 13
}
int main() {
    int x = 5; // 1
    int* ptr = &x; // 2
    f(ptr); // 21
    cout << "*ptr = " << *ptr << 'n'; // 22
    cout << "x = " << x << 'n'; // 23
}

在第一种情况下,指针是通过引用传递的,它指向y。事实上,在这种情况下,第21行涉及未定义的行为,因为y不再存在。再次,逐行分析:

1.  x = 5, y = NE, ptr = NE, fptr == NE
2.  x = 5, y = NE, ptr = &x, fptr == NE
11. x = 5, y = 30, ptr = &x, fptr == ptr
12. x = 5, y = 30, ptr = &y, fptr == ptr
13. x = 5, y = 30, ptr = &y, fptr == ptr
21. x = 5, y = NE, ptr = &y, fptr == NE

在此之后,值再次不变:但是,在第22行,您尝试获取ptr的地址。正如您所看到的,*ptr = y = NE,因此行为是未定义的。输出可以是任何内容。

(另一个注意事项是,您应该避免使用using namespace std;,因为它可能会导致名称冲突;请使用using std::cout;和类似的代码,如上面的代码所示。)