void DoWork(int n);
void DoWork(const int &n);
有什么区别?
答案 0 :(得分:48)
当您传递一个大型结构/类时,差异更为突出。
struct MyData {
int a,b,c,d,e,f,g,h;
long array[1234];
};
void DoWork(MyData md);
void DoWork(const MyData& md);
当您使用'normal'参数时,您可以按值传递参数,从而创建您传递的参数的副本。如果您使用const引用,则通过引用传递它,并且不会复制原始数据。
在这两种情况下,都无法从函数内部修改原始数据。
修改强>
在某些情况下,原始数据可能会按照Charles Bailey answer中的{{3}}所指示进行修改。
答案 1 :(得分:48)
重要的区别在于,当通过const
引用时,不会创建新对象。在函数体中,参数实际上是传入的对象的别名。
因为引用是const
引用,函数体不能直接更改该对象的值。它具有与传递值类似的属性,其中函数体也无法更改传入的对象的值,在这种情况下,因为参数是副本。
存在重大差异。如果参数是const
引用,但传递它的对象实际上不是const
,那么在函数调用期间可能会更改对象的值。
E.g。
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
,那么该函数可以(即使建议不通)使用强制转换更改其值。
e.g。
void DoWork(const int &n)
{
const_cast<int&>(n) = 22;
}
如果传入的对象实际上是const
,则会导致未定义的行为。
当参数通过const引用传递时,额外的成本包括解除引用,更糟糕的对象局部性,更少的编译优化机会。
当参数按值传递时,需要额外的成本来创建参数副本。通常,当对象类型很大时,这只是一个问题。
答案 2 :(得分:11)
您可以在函数
中传递三种方法按值传递
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的值。
答案 3 :(得分:6)
使用
void DoWork(int n);
n
是实际参数值的副本,更改函数中n
的值是合法的。随着
void DoWork(const int &n);
n
是对实际参数的引用,更改其值是不合法的。
答案 4 :(得分:2)
因为你们都没有提到关于const关键字......
const 关键字修改类型声明的类型或函数参数的类型,以防止值发生变化。 (来源:MS)
换句话说:通过引用传递参数会将其暴露给被调用者进行修改。使用 const 关键字可以防止修改。
答案 5 :(得分:0)
第一种方法按值传递n
,即n
的副本被发送到函数。第二个通过引用传递n
,这基本上意味着指向调用函数的n
的指针被发送到函数。
对于像int
这样的整数类型,作为const引用传递没有多大意义,因为引用的大小通常与引用的大小(指针)相同。在制作副本很昂贵的情况下,通常最好通过const引用。
答案 6 :(得分:0)
首先,没有cv限定引用的概念。因此术语“const引用”不正确,通常用于描述“对const的引用”。最好先谈谈这是什么意思。
$ 8.3.2 / 1-“符合条件的参考文献格式不正确,除非 cv-qualifiers是通过使用typedef(7.1.3)或 模板类型参数(14.3),在这种情况下是cv限定符 被忽略了。“
以下是差异
$ 13.1 - “只有最外层的const和volatile类型说明符 以这种方式忽略参数类型规范的级别; const和volatile类型说明符隐藏在参数类型中 规范是重要的,可用于区分 重载函数声明.112)。特别是对于任何类型的T, “指向T的指针”,“指向const T的指针”和“指向易失性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
}