说我有以下代码:
#include <iostream>
using namespace std;
int defaultvalue[] = {1,2};
int fun(int * arg = defaultvalue)
{
arg[0] += 1;
return arg[0];
}
int main()
{
cout << fun() << endl;
cout << fun() << endl;
return 0;
}
结果是:
2
3
这是有道理的,因为指针*arg
操纵了数组defaultvalue
。但是,如果我将代码更改为:
#include <iostream>
using namespace std;
int defaultvalue[] = {1,2};
int fun(int arg[] = defaultvalue)
{
arg[0] += 1;
return arg[0];
}
int main()
{
cout << fun() << endl;
cout << fun() << endl;
return 0;
}
但结果仍然是:
2
3
此外,当我打印出defaultvalue
:
cout << defaultvalue[0] <<endl;
结果是3。
我的问题是,在第二个例子中,函数参数是否应该按值传递,以便arg
的更改对defaultvalue
没有影响?
答案 0 :(得分:12)
我的问题是,在第二个例子中,函数参数是否应该按值传递,以便更改arg对defaultvalue没有影响?
没有
按值传递数组是不可能的(非常感谢C!)因此,作为“妥协”(读取:设计失败),函数参数列表中的int[]
实际上意味着{{1} }。所以你的两个程序完全相同。即使撰写int*
或int[5]
或int[24]
,实际上也意味着int[999]
。荒谬,不是吗?!
在C ++中,我们更喜欢将int*
用于数组:它是一个数组包装类,它具有适当的对象语义,包括可复制。您可以通过值将它们传递给函数。
实际上,std::array
主要是为了使这些愚蠢而令人惊讶的本机数组语义过时而引入的。
答案 1 :(得分:3)
当我们声明这样的函数时
int func(int* arg);
或者
int (func(int arg[])
他们在技术上是一样的。这是表达性的问题。在第一种情况下,API作者建议该函数应该接收指向单个值的指针;而在第二种情况下,它表明它需要一个数组(一些未指定的长度,例如可能以 nullptr 结尾)。
你也可以写
int (func(int arg[3])
再次在技术上是相同的,只是它会向API用户提示他们应该传递至少3个元素的int
数组。在这些情况下,编译器不会强制执行任何这些添加的修饰符。
如果你想将数组复制到函数中(以非黑客方式),你首先要在调用代码中创建它的副本,然后再传递它。或者,作为更好的选择,请使用std::array
(由@LightnessRacesinOrbit建议)。
答案 2 :(得分:0)
正如其他人所解释的那样
int arg[]
作为一个函数参数,这些括号内的任何内容并不重要(你甚至可以做int arg [5234234]并且它仍然可以工作]因为它不会改变它仍然只是一个普通的事实int *指针。
如果你真的想确保函数采用数组[],最好将它传递给
template<size_t size>
void func (const int (&in_arr)[size])
{
int modifyme_arr[100];
memcpy(modifyme_arr, in_arr, size);
//now you can work on your local copied array
}
int arr[100];
func(arr);
或者如果你想要100个元素
void func (const int (&arr)[100])
{
}
func(arr);
这些是传递一个简单数组的正确方法,因为它会保证你得到的是一个数组,而不仅仅是一个随机的int *指针,该函数不知道它的大小。当然你可以传递一个“计数”值,但是如果你犯了一个错误并且它不是正确的那个怎么办?然后你得到缓冲区溢出。