无效 (int a[]) { a[5] = 3; // 这是错的吗?}
我可以这样做以便修改传入的数组吗?
不好意思删了,有点新意。。。
我还有另一个问题可以回答我的问题:
如果我有
void Test(int a) {
}
void Best(int &a) {
}
这两个陈述是等价的吗?
Test(a);
Best(&a);
无效 (int a[]) { a[5] = 3; // 这是错的吗?}
我可以这样做以便修改传入的数组吗?
不好意思删了,有点新意。。。
我还有另一个问题可以回答我的问题:
如果我有
void Test(int a) {
}
void Best(int &a) {
}
这两个陈述是等价的吗?
Test(a);
Best(&a);
void Test(int a[])
{
a[5] = 3;
}
只是替代语法:
void Test(int* a)
{
*(a+5) = 3;
}
没有传递数组,只是一个指针。原始数组被修改。
至于你的第二次修订,给定:
void Test(int a)
{
}
void Best(int &a)
{
}
然后
Test(aa); // Passes aa by value. Changes to a in Test() do not effect aa
Best(aa); // Passes aa by reference; Changes to a DO effect aa
Best(&aa); // Is a syntax error: Passing a pointer instead of an int.
如果您不是通过引用而不是通过指针获取变量,则意味着该函数本质上是孤立的,获得了 a 的临时副本。无论您做什么(不尝试破解堆栈或类似的事情),您都无法在调用上下文中访问该值。
如果您对调用上下文有所了解,则可以根据对堆栈内容的一些预期来做事,但这通常是个坏主意。
如果您的方法采用本质上是 a* 的 a[],那么是的,您可以更改 a 指向的单元格的内容,但您将无法更改 a(指针)本身以指向其他内容。
没有。
从函数外部更改值的选项是通过引用调用 f(int& a)、通过指针调用 f(int* a) 以及使用全局(颤抖...)变量。
阅读此处给出的关于参数列表中int[]
和的区别的答案:和之间的区别。我真的在这个答案中投入了太多的爱!:)int*
char*
char[]
关于您关于您的Test
功能Best
的问题,James Curran提供了一个很好的答案。
您的原始功能应该可以工作。
如果你给它一个名字:
#include <iostream>
// Arrays always de-generate to pointers.
void plop(int a[]) // Make sure this function has a name.
{
a[5] = 3;
}
int main()
{
int test[] = { 1,1,1,1,1,1,1,1};
plop(test);
std::cout << test[5] << std::endl;
}
这是因为数组在作为参数传递给函数时总是退化为指针。所以这应该总是按预期工作。假设您没有超出数组末尾的索引。在 plop 内部,无法确定传递的数组的大小。
通过引用传递数组的主要动机是防止堆栈溢出和大对象的不必要复制。例如,想象一下如果我有这样的函数:
void foo(int x[500000000000]);
如果所有数组都是按值传递的,那么第一次调用该函数时,堆栈可能会溢出(但这当然是明显的夸张)。
这将在使用面向对象的方法时变得有用。假设你有这个而不是一个数组:
void foo(SomeClass x);
其中 SomeClass 是具有 500000000000 个数据成员的类。如果你调用这样的方法,编译器会一点一点地复制 x,这至少可以说是一个很长的过程。您在数组中使用的相同概念仍然适用,但您必须指定这是手动引用使用:
void foo(SomeClass &x);
(除非您有 64 位机器和大量 RAM,否则不要尝试创建一个 500000000000 元素数组开始)