【发布时间】:2011-02-07 07:15:54
【问题描述】:
void DoWork(int n);
void DoWork(const int &n);
有什么区别?
【问题讨论】:
标签: c++ parameters reference constants
void DoWork(int n);
void DoWork(const int &n);
有什么区别?
【问题讨论】:
标签: c++ parameters reference constants
第一个方法通过值传递n,即将n的副本发送到函数。第二个通过引用传递n,这基本上意味着将指向调用函数的n 的指针发送给函数。
对于像int 这样的整数类型,作为常量引用传递没有多大意义,因为引用的大小通常与引用(指针)的大小相同。在复制成本很高的情况下,通常最好通过 const 引用传递。
【讨论】:
当你传递一个大的结构/类时,差异会更加突出:
struct MyData {
int a,b,c,d,e,f,g,h;
long array[1234];
};
void DoWork(MyData md);
void DoWork(const MyData& md);
当您使用“普通”参数时,您按值传递参数,从而创建您传递的参数的副本。如果您使用的是 const 引用,则通过引用传递它,并且不会复制原始数据。
在这两种情况下,都不能从函数内部修改原始数据。
编辑:
在某些情况下,原始数据可能会被修改,正如Charles Bailey 在他的answer 中指出的那样。
【讨论】:
const?我的意思是,您的答案是否不适用于我们仅将“正常”参数与 ref 参数进行比较的情况?
const.. 只是有了const,编译器将帮助您避免修改原始数据.. 但这可以被故意绕过正如查尔斯·贝利所指出的那样……
有
void DoWork(int n);
n是实参值的副本,在函数内改变n的值是合法的。与
void DoWork(const int &n);
n是对实参的引用,改变其值是不合法的。
【讨论】:
因为你们都没有提到 const 关键字...
const 关键字修改类型声明的类型或函数参数的类型,防止值变化。 (来源:MS)
换句话说:通过引用传递参数会将其暴露给被调用者修改。使用 const 关键字可防止修改。
【讨论】:
重要的区别在于,当通过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 引用传递时,额外的成本包括取消引用、更差的对象局部性、更少的编译优化机会。
当参数通过值传递时,额外的成本是需要创建参数副本。通常,这仅在对象类型很大时才需要考虑。
【讨论】:
hot 和 cold。
首先,没有 cv 限定引用的概念。因此,术语“const 引用”是不正确的,通常用于描述“对 const 的引用”。最好开始谈论它的含义。
$8.3.2/1- "Cv 限定的引用格式不正确,除非 通过使用 typedef (7.1.3) 或 模板类型参数 (14.3),在这种情况下 cv-qualifiers 被忽略。”
这里有区别
$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
}
【讨论】:
你可以在函数中传递值的三种方法
按值传递
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 的值。
【讨论】:
x 的 值 被传递,即 3 而不是 x 本身。您所说的是通过引用传递,即第二个示例...