我的C++老师告诉我,如果函数内不对数组进行任何更改,那么应该仅使用引用传递。
我有一些非常大的向量在程序中传递。所有这些向量都将在函数内部被修改。我的矩阵大小约为[256*256][256][50]
...
在这种情况下,有没有什么特别的原因不使用引用传递?
据我所知,引用传递应该更快,并且消耗的内存更少吧?
我的C++老师告诉我,如果函数内不对数组进行任何更改,那么应该仅使用引用传递。
我有一些非常大的向量在程序中传递。所有这些向量都将在函数内部被修改。我的矩阵大小约为[256*256][256][50]
...
在这种情况下,有没有什么特别的原因不使用引用传递?
据我所知,引用传递应该更快,并且消耗的内存更少吧?
void foo( type array[100] );
void foo( type *array );
无论数组大小是多少(两个常见的错误:相信foo
内的array
是一个数组,并且相信它保证有100个元素)。
现在,在C++中,您实际上可以通过引用传递数组,但引用必须是数组的具体类型,包括大小:
void foo_array( type (&array)[100] );
这里的有趣语法告诉编译器函数将接受一个类型为type
的恰好100个元素的数组。其中的优点是编译器可以为您执行大小检查:
// assuming 'type' is defined
int main() {
type array0[99];
type array1[100];
foo( array0 ); // compiles, but if size=100 is assumed it will probably break
// equivalent to: foo( &array0[0] )
// foo2( array0 ); // will not compile, size is not 100
foo2( array1 ); // compiles, size is guaranteed to be 100
}
现在的问题是,你的函数只能用于大小为100的数组,而有时你可能需要对不同大小的数组执行相同的操作。有两种解决方案:将函数模板化为数组大小,这将为每个使用的大小提供大小安全的实现--编译时间和二进制大小较大,该模板将为每个不同的大小进行编译--或使用传值语法,这将使数组退化--大小不安全,必须作为额外参数传递,编译时间和二进制大小较小。第三个选项是将两者结合起来:
void foo( type *array, int size );
template <size_t N>
void foo( type (&array)[N] ) {
foo( array, N );
}
foo
,但编译器很可能会内联调用,并且生成的代码将等同于调用者提供数组和大小。不需要额外计算并且实现了真正数组的类型安全。你的老师是错的。如果需要修改数组,传递引用是正确的方法。如果不想被修改,就使用常量引用。
等一下..我有点害怕人们如何回答这个问题。就我所记得的,数组总是按引用传递。
void function(int array[])
{
std::cout << array[0] << '\n';
}
// somewhere else..
int array[2] = { 1, 2 };
function(array); // No copy happens here; it is passed by reference
void function(int &array[]) // error here
{ /* ... */ }
那你的意思是什么?
此外,许多人认为只有在函数内修改数组内容时才应该这样做。那么,对于常量引用呢?
void function(const int arr[])
{
std::cout << arr[0] << '\n';
}
-- 编辑
请问有人能告诉我如何在C++中不通过引用传递数组吗?
-- 编辑
哦,你是在谈论向量。好的,那么经验法则如下:
我漏掉了什么吗?
-- 编辑
void function(int (&array)[100])
)。谢谢,dribeas。
void foo(int *array)
并调用 foo(&array[0])
。但你可以通过引用传递数组:void foo(int (&array)[100])
。语法有些晦涩,大小必须明确声明(因为它是类型的一部分),但你可以这样做。 - David Rodríguez - dribeasvoid some_function(const some_object& o);
如果您尝试在函数体内修改对象的状态,这将生成编译错误。
此外,请注意数组始终按引用传递。
如果符合以下条件,您可以通过引用传递:
当您通过引用传递时,只有指针被传递到函数。如果您传递整个对象,则需要复制它,因此会消耗更多的 CPU 和内存。
将对象通过引用传递始终是一个不错的选择,但我们需要小心,并首先决定我们的目的/函数的目的是什么?
在这里,您必须做出选择,无论我们只读取对象的数据还是修改它。
假设您有一个接口如下:
void increament_value(int& a);
所以在这里,您可以修改传递的对象的值,但是当您传递敏感数据时,这可能是一场灾难,您可能会丢失原始数据并无法恢复,对吧?
因此,C++为您提供了一个功能,即不更改传递给函数的对象的值,并且始终将对象的const
引用传递给函数是一个明智的选择,例如:
double get_discounted_amount(const double &amount,double discount){
return (amount*discount/100);
}
这可以保证你的对象的实际值不会改变,但是这取决于你接口的目的,你是想改变它还是只是使用(读取)它。
我不认为有任何理由不能通过引用传递。或者你可以传递指针,但是有时候通过引用传递更好,因为它避免了空指针异常。
如果你的老师建议这种方式作为某种约定,那么如果有意义,可以自由打破它。你总可以在函数上方的注释中记录这一点。