当你想要改变原始变量的值时,我知道你通过引用传递给C ++中的函数。但是当你希望程序更有效时你也可以通过引用传递,如果你不想改变传递给函数的变量中的任何东西,你只需要使它成为const。我的问题是,为什么不总是让你的函数接受const引用传递的变量,如果它比传递变量更高效并让编译器在函数范围内创建一个新变量?为了扩展这个问题,一个函数WOULD需要复制一个变量而不是通过参数?
答案 0 :(得分:6)
当一个参数按值传递时,它是可修改的,复制它可能会被省略。例如,实现赋值运算符的规范方法如下所示:
T& T::operator= (T value) {
value.swap(*this);
return *this;
}
乍一看,它可能看起来效率低下,因为正在复制T
。但是,无论如何它都会被复制,即,如果需要复制,则会以这两种方式创建:
T& T::operator= (T const& value) {
T(value).swap(*this); // has to do a copy right here
return *this;
}
但是,对于第一个版本,可能根本不创建副本,例如
T f() { return T(); }
// ...
T x = ...;
x = f();
将f()
类型T
的结果分配给x
时,编译器可能会认为它不需要复制f()
的结果而是直接将它传递给赋值运算符。在这种情况下,如果赋值运算符通过const&
获取参数,则编译器具有以在赋值运算符内创建副本。在按值实现参数的实现中,它可以忽略副本!实际上,f()
的返回可能已经删除了副本,即对f()
的调用,以下任务可能只涉及对象的默认构造! ......对于许多现代编译器而言确实如此!
换句话说:如果您需要复制参数,通过值传递它可以避免创建副本的需要。此外,您可以从值参数std::move()
而不是const&
个参数。
答案 1 :(得分:2)
但是,当你想要程序时,你也可以通过引用传递 更高效,如果你不想改变任何东西 变量传递给函数,你只需要使它成为const。
这是错的。传递基本类型(int,float,char ....)的参数比通过引用传递它们更有效。 const&通过BIG OBJECT更有效。因为引用是必要对象的别名,所以编译器需要处理更多信息。
答案 2 :(得分:1)
参考文献基本上是一个特殊的合约,其中的回报是一些语法糖和简单性。在函数体中,编译器可以自由地消除引用,但是当它们作为参数传递时,实际传递的是指针。
结果是使用引用可能会产生差异成本。
void func(int& i) {
int j = i; // secretly a dereference
// ...
}
会产生与
相同的开销void func(int* i) {
int j = *i;
// ...
}
本地便利引用通常可以优化,但引用参数必须至少在第一次使用时才被取消引用。