C++ 常量引用和普通参数的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2627166/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:08:39  来源:igfitidea点击:

Difference between const reference and normal parameter

c++parametersreferenceconst

提问by Pirate for Profit

void DoWork(int n);
void DoWork(const int &n);

What's the difference?

有什么不同?

回答by Afriza N. Arief

The difference is more prominent when you are passing a big struct/class.

当您传递一个大的结构/类时,差异更加突出。

struct MyData {
    int a,b,c,d,e,f,g,h;
    long array[1234];
};
void DoWork(MyData md);
void DoWork(const MyData& md);

when you use use 'normal' parameter, you pass the parameter by value and hence creating a copy of the parameter you pass. if you are using const reference, you pass it by reference and the original data is not copied.

当您使用 use 'normal' 参数时,您按值传递参数,从而创建您传递的参数的副本。如果您使用的是 const 引用,则通过引用传递它并且不会复制原始数据。

in both cases, the original data cannot be modified from inside the function.

在这两种情况下,不能从函数内部修改原始数据。

EDIT:
In certain cases, the original data might be able to get modified as pointed out by Charles Baileyin his answer.

编辑:
在某些情况下,原始数据可能会像Charles Bailey在他的回答中指出的那样进行修改。

回答by CB Bailey

The important difference is that when passing by constreference, no new object is created. In the function body, the parameter is effectively an alias for the object passed in.

重要的区别在于,通过const引用传递时,不会创建新对象。在函数体中,参数实际上是传入对象的别名。

Because the reference is a constreference the function body cannot directly change the value of that object. This has a similar property to passing by value where the function body also cannot change the value of the object that was passed in, in this case because the parameter is a copy.

因为引用是一个const引用,所以函数体不能直接改变那个对象的值。这与按值传递具有相似的属性,其中函数体也不能更改传入的对象的值,在这种情况下,因为参数是副本。

There are crucial differences. If the parameter is a constreference, but the object passed it was not in fact constthen the value of the object may be changed during the function call itself.

存在关键差异。如果参数是一个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);
}

Also if the object passed in was not actually constthen the function could (even if it is ill advised) change its value with a cast.

此外,如果传入的对象实际上不是,const则该函数可以(即使不明智)通过强制转换来更改其值。

e.g.

例如

void DoWork(const int &n)
{
    const_cast<int&>(n) = 22;
}

This would cause undefined behaviour if the object passed in was actually const.

如果传入的对象实际上是 ,这将导致未定义的行为const

When the parameter is passed by const reference, extra costs include dereferencing, worse object locality, fewer opportunities for compile optimizing.

当参数通过 const 引用传递时,额外的成本包括取消引用、更糟糕的对象局部性、更少的编译优化机会。

When the parameter is passed by value and extra cost is the need to create a parameter copy. Typically this is only of concern when the object type is large.

当参数按值传递时,额外的成本是需要创建参数副本。通常,这仅在对象类型较大时才需要关注。

回答by sneha

There are three methods you can pass values in the function

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

  1. Pass by value

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

    Output: 3. Disadvantage: When parameter xpass through ffunction then compiler creates a copy in memory in of x. So wastage of memory.

  2. Pass by reference

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

    Output: 13. It eliminate pass by value disadvantage, but if programmer do not want to change the value then use constant reference

  3. Constant reference

    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;
    }
    

    Output: Throw error at n = n + 10because when we pass const reference parameter argument then it is read-only parameter, you cannot change value of n.

  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 的值。

回答by Avi

With

 void DoWork(int n);

nis a copy of the value of the actual parameter, and it is legal to change the value of nwithin the function. With

n是实参值的副本,n在函数内改变的值是合法的。和

void DoWork(const int &n);

nis a reference to the actual parameter, and it is not legal to change its value.

n是对实际参数的引用,改变它的值是不合法的。

回答by Aoi Karasu

Since none of you mentioned nothing about the const keyword...

因为你们都没有提到 const 关键字......

The constkeyword modifies the type of a type declaration or the type of a function parameter, preventing the value from varying. (Source: MS)

常量关键字修改类型声明的类型或函数参数的类型,从而防止改变值。(来源:女士)

In other words: passing a parameter by reference exposes it to modification by the callee. Using the constkeyword prevents the modification.

换句话说:通过引用传递参数会将其暴露给被调用者修改。使用const关键字可防止修改。

回答by Andreas Brinck

The first method passes nby value, i.e. a copy of nis sent to the function. The second one passes nby reference which basically means that a pointer to the nwith which the function is called is sent to the function.

第一种方法n按值传递,即向n函数发送的副本。第二个是通过n引用传递的,这基本上意味着一个指向n调用函数的指针被发送到函数。

For integral types like intit doesn't make much sense to pass as a const reference since the size of the reference is usually the same as the size of the reference (the pointer). In the cases where making a copy is expensive it's usually best to pass by const reference.

对于整数类型int,作为 const 引用传递没有多大意义,因为引用的大小通常与引用(指针)的大小相同。在制作副本成本很高的情况下,通常最好通过 const 引用传递。

回答by Chubsdad

Firstly, there is no concept of cv-qualified references. So the terminology 'const reference' is not correct and is usually used to describle 'reference to const'. It is better to start talking about what is meant.

首先,没有 cv 限定引用的概念。所以术语“const 引用”是不正确的,通常用于描述“对const 的引用”。最好开始谈论是什么意思。

$8.3.2/1- "Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through the use of a typedef (7.1.3) or of a template type argument (14.3), in which case the cv-qualifiers are ignored."

$8.3.2/1-“Cv 限定的引用格式错误,除非通过使用 typedef (7.1.3) 或模板类型参数 (14.3) 引入 cv 限定符,在这种情况下,cv-限定符被忽略。”

Here are the differences

以下是差异

$13.1 - "Only the const and volatile type-specifiers at the outermost level of the parameter type specification are ignored in this fashion; const and volatile type-specifiers buried within a parameter type specification are significant and can be used to distinguish overloaded function declarations.112). In particular, for any type T, “pointer to T,” “pointer to const T,” and “pointer to volatile T” are considered distinct parameter types, as are “reference to T,” “reference to const T,” and “reference to volatile T.”

$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 .5/3
}