关于将数组传递给函数的最佳实践,我有一个广泛的问题。
所以在过去我用C编程时我想要一个函数让它的输入是一个数组,我会声明函数输入参数是一个指针。这种方法效果相当不错。
但是,我开始用C ++编写更多内容,并试图确定将数组传递给函数的最佳实践。所以我注意到在C ++中通过引用传递对象是很流行的,这样可以避免昂贵的复制操作。但是,当我谷歌将数组传递给函数时,我读到的语句表明数组是通过引用自动传递的......那么这个问题是什么呢?为什么数组会通过引用自动传递?并且假设我不希望函数修改数组,是否可以传递const数组?
我很难让我的测试程序进行编译。所以我很好奇是否有人能解释将数组传递给C ++中的函数意味着什么以及它与C的区别。
谢谢!
答案 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::array
或std::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(基于迭代器的处理)几乎不需要自己管理阵列。