这一直困扰我一个多星期了。我可能错过了解释这个问题的帖子,但是我已经阅读了很多帖子/文章,他们要么不告诉我任何我不知道的事情,要么告诉我。
考虑一下:
#include<iostream>
using namespace std;
void poo(int *currArray){
cout << "*currArray: " << currArray << endl;
int * blah = new int [5];
cout << "blah: " << blah << endl;
currArray = blah;
cout << "currArray after switch " << currArray << endl;
}
int main(){
int * foo = new int [5];
cout << "foo: " << foo << endl;
poo(foo);
cout << "foo after poo " << foo << endl;
}
产生输出:
foo: 0x7ffdd5818f20
*currArray: 0x7ffdd5818f20
blah: 0x7ffdd5818ef0
currArray after switch 0x7ffdd5818ef0
foo after poo 0x7ffdd5818f20
正如您所看到的,当地址切换发生在函数内部时,它不会转移到主函数。我也知道这是在泄漏记忆,但我不认为这与这个问题有关。
我的理解是数组本质上指向其第一个元素的地址。我也理解数组是通过“引用”传递的。即,传递数组的地址。
那么为什么poo
之后地址切换不会持续存在?我是否未将currArray
的指针({1}}的指针更改为foo
的指针?
答案 0 :(得分:2)
什么是指针?它是一个包含内存地址的变量。它可以被复制,可以被引用,你甚至可以获取它的地址。因此,当您将函数声明为void poo(int *currArray)
时,将传递的参数的值复制到变量currArray
中。因此,currArray
现在包含与foo
相同的地址。但是,当您更改currArray
的值时,您只会更改currArray
的值,因为它是副本而不是引用。
你可以看到Carl关于如何通过引用传递指针的答案。另一种可以修改foo
的方法是将foo
的地址传递给该函数。从现在开始知道foo
在内存中的哪个位置,您可以通过取消引用它并为其分配blah
的地址来更改其值。当然,你应该首先释放foo
(通过currArray
)占用的内存,因为如果你不能在之后做到这一点并且会发生内存泄漏。
以下是示例代码:
#include<iostream>
void poo(int **currArray)
{
std::cout << "currArray: " << *currArray << std::endl;
int *blah = new int[5];
std::cout << "blah: " << blah << std::endl;
delete[] *currArray; // clean after ourselves
*currArray = blah;
std::cout << "currArray after switch " << *currArray << std::endl;
}
int main()
{
int *foo = new int[5];
std::cout << "foo: " << foo << std::endl;
poo(&foo);
std::cout << "foo after poo " << foo << std::endl;
delete[] foo; // clean after ourselves
}
foo: 0x560b3e9ffc20
currArray: 0x560b3e9ffc20
blah: 0x560b3ea00c50
currArray after switch 0x560b3ea00c50
foo after poo 0x560b3ea00c50
答案 1 :(得分:1)
这里需要注意的重要一点是,由于指针是对象,因此在将foo
传递给poo
时,您将按值获取指针。因此,函数内的赋值实际上仅应用于局部参数currArray
。为了使指针保持在范围之外,你必须声明你的函数:void poo(int *& currArray);
,尽管这对数组不起作用。这意味着它是对指向int的指针的引用。否则指针将按值传递。
话虽如此,你正在尝试做的事情,在函数poo
内部指定一个本地堆栈对象的指针并不是很好,因为一旦函数返回你的另一个指针就会指向某个东西被破坏,这将导致不明确的行为。
您应该考虑在任何good C++ book中阅读有关指针,引用和参数传递的更多信息。
虽然你是正确的,数组的地址是通过的,指针本身是通过值传递的,所以函数内的本地指针指向同一个地址,但它的指针不同于主指针中的指针。
此外,您应该强烈考虑使用std::vector
而不是原始数组,因为这样可以更容易使用,维护并且没有太大的性能差异(如果有的话)。
这是一段代码:
void poo(int *& currArray){
/* ... */
}
int main(){
int foo[5];
int* doo = foo;
cout << "foo: " << doo << endl;
poo(doo);
cout << "foo after poo " << doo << endl;
}
你必须做doo的原因是你不能将非const左值绑定到数组foo
本身。如果你使它成为常量,你就无法在该函数中进行分配。如果你分配了那个数组,那就好了,因为foo的类型是int*
。
答案 2 :(得分:1)
关于通过值和按引用传递,存在一些混淆。对于数组尤其如此。
我不会在这里打扰你的全貌,但我会尽可能地解决你的误解:
&
或&&
,否则所有参数都按值传递。 void foo(int& a)
&
因此没有通过引用传递任何内容*
和[]
运算符访问数组的元素。它们将允许您访问实际数组元素,而不是它们的副本。这不知何故感觉就像通过引用传递数组一样。因此混乱。因此,您可以修改函数内部的数组元素,您将在main
中看到效果。但是如果你修改指向数组的指针,你就不会在main
中看到任何效果,因为该指针是按值传递的。
答案 3 :(得分:0)
currArray
不是别名,它是一个函数本地对象,其值已经初始化为通过参数传递机制传递的值,并且函数中发生的事情会保留在该函数中。您可以将它声明为对指针的引用,然后使用它来修改传递的任何实际指针(但不是数组),但再次,这是引用如何工作,而不是某种参数魔法。