int a;
void DoWork(const int &n)
{
a = n * 2; // If n was a reference to a, n will have been doubled
f(); // Might change the value of whatever n refers to
}
int main()
{
DoWork(a);
}
void f(int &n){
cout << 1;
n++;
}
void f(int const &n){
cout << 2;
//n++; // Error!, Non modifiable lvalue
}
int main(){
int x = 2;
f(x); // Calls overload 1, after the call x is 3
f(2); // Calls overload 2
f(2.2); // Calls overload 2, a temporary of double is created $8.5/3
}
8条答案
按热度按时间inn6fuwd1#
重要的区别在于,当通过
const
引用传递时,不会创建新的对象。在函数体中,参数实际上是传入对象的别名。因为引用是
const
引用,所以函数体不能直接更改该对象的值。这与按值传递具有类似的属性,按值传递函数体也不能更改传入的对象的值,在这种情况下,因为参数是副本。如果参数是一个
const
引用,但传递给它的对象实际上不是const
,那么对象的值可能在函数调用过程中改变。例如
另外,如果传入的对象实际上不是
const
,那么函数可以(即使这是不明智的)通过强制类型转换来更改其值。例如:
如果传入的对象实际上是
const
,这将导致未定义的行为。当参数通过常量引用传递时,额外的代价包括解引用、更差的对象局部性、更少的编译优化机会。
当参数按值传递时,需要创建一个参数副本,这是一个额外的开销。通常,只有当对象类型很大时,才需要考虑这一点。
k3bvogb12#
当你传递一个大的结构体/类时,这个区别就更加明显了:
当使用"normal"参数时,按值传递参数,从而创建所传递参数的副本。如果使用常量引用,则按引用传递,并且不复制原始数据。
在这两种情况下,都不能从函数内部修改原始数据。
在某些情况下,原始数据可能会被修改,正如Charles Bailey在他的回答中指出的那样。
xdyibdwo3#
有三种方法可以在函数中传递值
1.按值传递
产量:3.缺点:当参数
x
通过f
函数传递时,编译器会在内存中创建x的副本,因此会浪费内存。1.通过引用传递
输出:13。它消除了通过值传递的缺点,但如果程序员不想改变值,则使用常量引用
1.常数参考
输出:在
n = n + 10
抛出错误,因为当我们传递const引用参数时,它是只读参数,您无法更改n的值。gmxoilav4#
与
n
是实参值的副本,在函数中修改n
的值是法律的的。n
是对实际参数的引用,更改其值是不法律的的。prdp8dxp5#
既然你们都没提到常量关键字...
换句话说:通过引用传递参数会暴露被调用方的修改。2使用const关键字可以防止修改。
ntjbwcob6#
第一种方法通过传值传递
n
,也就是说,n
的一个副本被发送到函数;第二种方法通过传址传递n
,也就是说,一个指向n
的指针被发送到函数。对于
int
这样的整型类型,作为const引用传递没有多大意义,因为引用的大小通常与引用(指针)的大小相同。在复制开销很大的情况下,通常最好通过const引用传递。vu8f3i0k7#
首先,没有cv限定引用的概念,所以术语“const reference”是不正确的,通常用来描述“reference to const”,最好开始讨论它的含义。
$8.3.2/1-“CV限定引用是格式错误的,除非通过使用typedef(7.1.3)或模板类型参数(14.3)引入CV限定符,在这种情况下,CV限定符将被忽略。”
以下是不同之处
$13.1 -“只有在参数类型规范最外层的const和volatile类型说明符被忽略;埋在参数类型规范内的const和volatile类型说明符是重要的,并且可用于区分重载函数声明。112)具体而言,对于任何类型T,“指向T的指针”、“指向const T的指针”和“指向volatile T的指针”被认为是不同的参数类型,“指向T的引用”、“指向const T的引用”和“指向volatile T的引用”也是如此。
xzv2uavs8#
此外,您可以使用
const int& x
将其初始化为r值,这将导致您无法更改x或将其与其他值绑定。