C/C++ 函数const形参

以下是《C++ Primer 中文版(Edition 4)》    7.2.1非引用形参 -- 2 const 形参 章节中的一段话:


在调用函数时,如果该函数使用非引用的非const形参,则既可以给该函数传递const实参也可传递非const实参
     const int i = 3, j = 6;
     int k = rgcd(3, 6);
   // ok: k initialized to 3
这种行为源于const对象的标准初始化规则。因为初始化赋值了初始化式的值,所以可用const对象初始化非const对象,反之亦然
如果将形参定义为非引用的const类型
void fcn(const int i) { /* fcn can read but not write to i */ }
则在函数中,不可以改变实参的局部副本。由于实参仍然是以副本的形式传递,因此传递给函数的既可以是const对象也可以是非const对象
尽管函数的形参是const,但是编译器却将fcn的定义是为其形参被声明为普通的int型:
     void fcn(const int i) { /* fcn can read but not write to i */ }
     void fcn(int i) { /* ... */ }            // error: redefines fcn(int)
这种用法是为了支持对C语言的兼容,因为在C语言中,具有const形参或非const形参的函数并无区别。


“编译器却将fcn的定义是为其形参被声明为普通的int型"

这句话的意思并不是说在void fcn(const int i)中可以对形参i进行修改,而是说编译后的汇编结果,对于形参int i和const int i的处理的汇编代码是一样的。

如果在void fcn(const int i)中对形参i进行修改,编译仍然会报错,这是编译检查,与真正的编译阶段是不同的。


//a1.c
int foo(const int arg)                                                          
{                                                                               
    int val1 = arg << 1;                                                        
    return val1;                                                                
}


//a2.c
int foo(int arg)                                                                
{                                                                               
    int val1 = arg << 1;                                                        
    return val1;                                                                
}

gcc -S a1.c 和 gcc -S a2.c 生成汇编文件,对比可以发现a1.s和a2.s的汇编是相同的。同样将a1.c, a2.c分别命令为a1.cpp, a2.cpp 使用g++ -S 编译出的结果也是一样的。

"因为在C语言中,具有const形参或非const形参的函数并无区别"

//a1.s
    .file   "a1.c"                                                              
    .text                                                                       
    .globl  foo                                                                 
    .type   foo, @function                                                      
foo:                                                                            
.LFB0:                                                                          
    .cfi_startproc                                                              
    pushl   %ebp                                                                
    .cfi_def_cfa_offset 8                                                       
    .cfi_offset 5, -8                                                           
    movl    %esp, %ebp                                                          
    .cfi_def_cfa_register 5                                                     
    subl    $16, %esp                                                           
    movl    8(%ebp), %eax                                                       
    addl    %eax, %eax                                                          
    movl    %eax, -4(%ebp)                                                      
    movl    -4(%ebp), %eax                                                      
    leave                                                                       
    .cfi_restore 5                                                              
    .cfi_def_cfa 4, 4                                                           
    ret                                                                         
    .cfi_endproc                                                                
.LFE0:                                                                          
    .size   foo, .-foo                                                          
    .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"                               
    .section    .note.GNU-stack,"",@progbits

//a2.s

    .file   "a2.c"                                                              
    .text                                                                       
    .globl  foo                                                                 
    .type   foo, @function                                                      
foo:                                                                            
.LFB0:                                                                          
    .cfi_startproc                                                              
    pushl   %ebp                                                                
    .cfi_def_cfa_offset 8                                                       
    .cfi_offset 5, -8                                                           
    movl    %esp, %ebp                                                          
    .cfi_def_cfa_register 5                                                     
    subl    $16, %esp                                                           
    movl    8(%ebp), %eax                                                       
    addl    %eax, %eax                                                          
    movl    %eax, -4(%ebp)                                                      
    movl    -4(%ebp), %eax                                                      
    leave                                                                       
    .cfi_restore 5                                                              
    .cfi_def_cfa 4, 4                                                           
    ret                                                                         
    .cfi_endproc                                                                
.LFE0:                                                                          
    .size   foo, .-foo                                                          
    .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"                               
    .section    .note.GNU-stack,"",@progbits







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值