繁体   English   中英

const 引用和普通参数有什么区别?

[英]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在他的回答中指出的那样进行修改。

您可以通过三种方法在函数中传递值

  1. 按值传递

    void f(int n){ n = n + 10; } int main(){ int x = 3; f(x); cout << x << endl; }

    输出:3. 缺点:当参数x通过f函数时,编译器会在 x 的内存中创建一个副本。 所以浪费内存。

  2. 通过引用传递

    void f(int& n){ n = n + 10; } int main(){ int x = 3; f(x); cout << x << endl; }

    输出:13。它消除了按值传递的缺点,但如果程序员不想更改值,则使用常量引用

  3. 常量参考

    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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM