C ++函数的默认参数是如何传递的?

时间:2016-02-03 12:02:30

标签: c++ parameter-passing

说我有以下代码:

#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没有影响?

3 个答案:

答案 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 *指针,该函数不知道它的大小。当然你可以传递一个“计数”值,但是如果你犯了一个错误并且它不是正确的那个怎么办?然后你得到缓冲区溢出。