[英]What is the difference between a const reference and normal parameter?
void DoWork(int n);
void DoWork(const int &n);
有什么不同?
重要的区别在于,通过const
引用传递时,不会创建新对象。 在函数体中,参数实际上是传入对象的别名。
因为引用是一个const
引用,所以函数体不能直接改变那个对象的值。 这与按值传递具有相似的属性,其中函数体也不能更改传入的对象的值,在这种情况下,因为参数是副本。
存在关键差异。 如果参数是一个const
引用,但传递给它的对象实际上不是const
那么对象的值可能会在函数调用本身期间改变。
例如
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);
}
此外,如果传入的对象实际上不是const
则该函数可以(即使不明智)通过强制转换来更改其值。
例如
void DoWork(const int &n)
{
const_cast<int&>(n) = 22;
}
如果传入的对象实际上是const
这将导致未定义的行为。
当参数通过 const 引用传递时,额外的成本包括取消引用、更糟糕的对象局部性、更少的编译优化机会。
当参数按值传递时,额外的成本是需要创建参数副本。 通常,这仅在对象类型较大时才需要关注。
当您传递一个大的结构/类时,差异更加突出。
struct MyData {
int a,b,c,d,e,f,g,h;
long array[1234];
};
void DoWork(MyData md);
void DoWork(const MyData& md);
当您使用 use 'normal' 参数时,您按值传递参数,从而创建您传递的参数的副本。 如果您使用的是 const 引用,则通过引用传递它并且不会复制原始数据。
在这两种情况下,不能从函数内部修改原始数据。
编辑:
在某些情况下,原始数据可能会像Charles Bailey在他的回答中指出的那样进行修改。
您可以通过三种方法在函数中传递值
按值传递
void f(int n){ n = n + 10; } int main(){ int x = 3; f(x); cout << x << endl; }
输出:3. 缺点:当参数x
通过f
函数时,编译器会在 x 的内存中创建一个副本。 所以浪费内存。
通过引用传递
void f(int& n){ n = n + 10; } int main(){ int x = 3; f(x); cout << x << endl; }
输出:13。它消除了按值传递的缺点,但如果程序员不想更改值,则使用常量引用
常量参考
void f(const int& n){ n = n + 10; // Error: assignment of read-only reference 'n' } int main(){ int x = 3; f(x); cout << x << endl; }
输出:在n = n + 10
处抛出错误,因为当我们传递 const 引用参数时,它是只读参数,您不能更改 n 的值。
和
void DoWork(int n);
n
是实参值的副本,在函数内改变n
的值是合法的。 和
void DoWork(const int &n);
n
是对实际参数的引用,改变它的值是不合法的。
因为你们都没有提到 const 关键字......
const关键字修改类型声明的类型或函数参数的类型,防止值发生变化。 (来源:女士)
换句话说:通过引用传递参数会将其暴露给被调用者修改。 使用const关键字可防止修改。
第一种方法按值传递n
,即n
的副本被发送到函数。 第二n
通过引用传递n
,这基本上意味着一个指向调用函数的n
的指针被发送到函数。
对于像int
这样的整数类型,作为 const 引用传递没有多大意义,因为引用的大小通常与引用(指针)的大小相同。 在制作副本成本很高的情况下,通常最好通过 const 引用传递。
首先,没有 cv 限定引用的概念。 所以术语“const 引用”是不正确的,通常用于描述“对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 的引用”。
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
}
此外,您可以使用const int& x
将其初始化为 r 值,这将导致您无法更改 x 或将其与其他值绑定。
const int& x = 5; // x is a constant reference to r-value 5
x = 7; // expression is not a modifable value
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.