const参考和正常参数之间的差异

时间:2010-04-13 05:26:04

标签: c++ parameters reference const

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

有什么区别?

7 个答案:

答案 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)

您可以在函数

中传递三种方法
  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的值。

答案 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
}