将数组传递给函数 - 指针与引用(C ++与C)

时间:2016-02-21 03:24:31

标签: c++ c arrays function pointers

关于将数组传递给函数的最佳实践,我有一个广泛的问题。

所以在过去我用C编程时我想要一个函数让它的输入是一个数组,我会声明函数输入参数是一个指针。这种方法效果相当不错。

但是,我开始用C ++编写更多内容,并试图确定将数组传递给函数的最佳实践。所以我注意到在C ++中通过引用传递对象是很流行的,这样可以避免昂贵的复制操作。但是,当我谷歌将数组传递给函数时,我读到的语句表明数组是通过引用自动传递的......那么这个问题是什么呢?为什么数组会通过引用自动传递?并且假设我不希望函数修改数组,是否可以传递const数组?

我很难让我的测试程序进行编译。所以我很好奇是否有人能解释将数组传递给C ++中的函数意味着什么以及它与C的区别。

谢谢!

3 个答案:

答案 0 :(得分:9)

在C和C ++中,声明一个函数来获取一个数组参数,例如在下面的例子中,实际上会导致函数获取一个指针。例如:

void foo(int arr[]);

此功能签名与:

相同
void foo(int *arr);

因此,当您尝试在C或C ++中传递数组时,您已经避免了复制数组的任何开销。

  

为什么数组会通过引用自动传递?

它们只是在宽松的意义上通过引用传递。它们不是作为C ++引用传递的,如下所示:

void foo(int (&arr)[10]); // arr is a reference to an array of 10 ints

C行为的原因是因为他们认为通过值传递数组永远不会被使用,因为昂贵的副本。 C ++具有相同行为的原因仅仅是为了兼容性。

经验表明,数组参数的特殊行为是一个坏主意,因此这是应该避免在C ++中使用原始数组的众多原因之一。问题是以任何一种方式传递数组都是危险的:

void foo(int arr[10]) { arr[9] = 0; }

void bar() {
    int data[] = {1, 2};
    foo(data);
}

上面的代码是错误的,但编译器认为一切都很好,并且没有发出有关缓冲区溢出的警告。

而是使用std::arraystd::vector,它们具有一致的值语义,并且缺少产生上述错误的“特殊”行为。

  

让我说我不希望函数修改数组,是否可以传递const数组?

你可以:

void foo(int const arr[]);
void foo(int const *arr);

void foo(int const (&arr)[10]);
  

所以我很好奇是否有人能解释将数组传递给C ++中的函数意味着什么以及它与C的区别。

如果你使用在C语言中工作的语法,那么它根本就没有区别。

答案 1 :(得分:1)

C ++中的最佳实践是根本不使用C风格的数组。

在C ++中,C样式的数组可以像它们在C中一样传递。这可以被描述为通过引用传递数组的内容,因为该函数可以通过间接传递的指针来修改调用者的数组。

在C ++中,如果你确实想要使用C风格的数组,你可以选择通过指针传递(如在C中),并使用C ++引用(例如see here)进行传递。

答案 2 :(得分:0)

C++中,最佳做法是允许您的数组由容器管理,std::array(编译时修复)或std::vector(运行时变量)。

通常情况下,如果您不希望修改数组,则会通过 const reference 传递:

void func(const std::vector<int>& v); // pass by const reference

否则,通过普通引用修改函数传递中的数组:

void func(std::vector<int>& v); // pass by reference

更复杂和通用的是将迭代器传递给您的函数,以便它可以对整个数组或仅仅是其中的一部分进行操作。

template<typename Iterator>
void func(Iterator begin, Iterator end);

这将被称为:

func(v.begin(), v.end()); // operate on the whole array

容器,迭代器和algorithms(基于迭代器的处理)几乎不需要自己管理阵列。