您的位置:首页 > 编程语言 > C语言/C++

C++中的const用法【02】----函数的参数和返回值

2015-01-26 21:47 260 查看
如果按值传递对象,它意味着传递的参数在函数中是不能被修改的。

如果按常量返回用户定义类型的对象的值,这意味着返回值不能被修改。

如果传递参数并返回地址,const 将保证改地址不会被改变。

1. 传递const 值

如果参数是按值传递,那么可用const 修饰指定参数。

void fun1(int value1 , const int value2) {
value1 ++ ; // Safe
value2 ++ ; // Error ,被const 修饰的变量不能被更改
}


这里有一个规定,就是value2已被const 修饰,在fun1()函数的整个生命周期中,value2都无法被修改。由于采用的是按值传递,因此fun1()在这里会定义2个实参的副本作为形参,并将第二个形参设置为const 对象。

const 在函数中的用法很简单,就是将一个对象修饰成“无法被修改的”,因此可以将它试做被调的工具而非主调的。(因为上述过程对于主调来说是不知情的)

为了使得程序更加清晰,最好将const 限定参数放在函内部而非它的参数列表,这样可以使得被调的形参列表与主调相同。

#include <iostream>
using namespace std ;

void fun(int value1) {
const int& i = value1 ;
i ++ ;          //Error,i is a const object;
<span style="white-space:pre">	</span>value ++ ;
}

int main (void) {
int a = 1 , b = 2 ;
fun(a) ;
return 0 ;
}


我们可以借助引用,让const 限定参数这一过程在函数内部实现,但需要注意的是,在内部实现的情况下,我们定义的引用变量是const 的,但形参依然是非const ,这意味着形参依旧可以被改变。因此,我们一旦使用了引用去实现,在接下来的描述中,要尽量使用const 修饰的引用变量而非原参数。

2. 返回const 值

对函数的返回值而言,const 也有类似的功能:将一个函数的返回值限定为常量。

其声明形式如下:

const int fun() ;

这样的形式会使得函数框架中原变量不会修改。

#include <iostream>
using namespace std ;

int fun3() {
return 1 ;
}

int fun4() {
return 2 ;
}

int main (void) {
const int i = fun3() ;  //It is safe ;
int j = fun4() ;        //It is also safe ;
return 0 ;
}


对于内建类型(int , double , char等)而言,按值返回的对象是否是一个const ,都无关紧要,因为它返回的是仅仅一个值,就如同

const int i = 0 ;
int j = i ;

一样,是一个简单的赋值过程,因此对于主调的接收值类型来说,有没有const 都可以。但在没有必要时最好不要带上,不然容易引起混淆。

而当处理用户自定义的类型(struct,class)时,按值返回常量却是非常重要的,如果一个函数按值返回一个类类型的const 对象时,那么这个函数的返回值就不能作为一个左值(即不能出现在等号左边,不能被赋值或被修改)

#include <iostream>
using namespace std ;

class Example {
private:
int i_ ;
public:
Example(int i) : i_(i) {}
void modify() {
i_ ++ ;
}
// default constructor
///~
// copy constructor
///~
};

Example fun1() {
return Example() ;
}

const Example fun2() {
return Example() ;
}

int main(void) {
fun1() = Example(1) ;   //safe
fun1().modify() ;       //safe
fun2() = Example(1) ;   //error , fun2的返回值类型是const Example , 即返回的对象不能被改变
fun2().modify() ;       //error , const对象不能调用非const成员函数
return 0 ;
}


<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="white-space:pre">	</span>fun1()返回一个非const 对象,而fun2()返回一个const 对象,只有非const返回值能作为一个左值引用。当按值返回一个类对象时,如果不希望这个类对象被改变,就请大家使用const 来修饰。</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">
</span>

总结:在按值传递内建类型时,const 没有意义的原因是,编译器已经成功的阻止它成为左值,因为这样的函数返回的是一个值,而不是一个变量,一个值只能被其他对象接收,而不能被更改。因此,只有按值返回一个用户定义的类类型时,const 的修饰才会变得不可或缺。

3. 传递和返回地址

如果传递或返回一个地址,那么其处置可能被通过操纵地址所改变,使用const 修饰可以有效的阻止这类事情的发生。并且,无论什么时候将地址传递给函数,都英爱尽可能的使用const 去限制。

#include <iostream>
using namespace std ;

void fun1(int *) {}

void fun2(const int * cip) {
* cip = 2 ;             //error,const int * 是限制指针所指向的值不能被改变,因此无法赋值
int i = * cip ;
int * cp2 = cip ;       //error,不能将const int * 赋值给int * ;
}

const char * fun3() {
return "result of fun3()" ;
}

const int * const fun4() {
static int i ;
return &i ;
}

int main(void) {
int x = 0 ;
int * ip = &x ;
const int * cip = &x ;
fun1(ip) ;
fun1(cip) ;
fun2(ip) ;                              //!!error,不能用int * 赋值给const int *
fun2(cip) ;
char * cp = fun3() ;                    //!!error,不能用const char * 赋值给char *
const char * ccp = fun3() ;
int * ip2 = fun4() ;                    //!!error,不能用const int * const 赋值给int *
const int * const ccip = fun4() ;
const int * cip2 = fun4() ;            <span style="color:#ff0000;"> //特别强调,这个是正确的,可以将const int * const 赋给const int * ;
//因为const int * const 和 const int *都表示指针的指向被const修饰不能随意改变,这回与函数来说已经足够了
//它指向的值是不是const编译器都不会再去判断,因为接下来执行的是赋值过程
//就像我们刚才说的,对于按值传递的内建类型的返回值常量有无const修饰都没有太大区别</span>
*fun4() = 1 ;                           //!!error,返回的指针本身和它所指向的对象都无法更改,因此不能作为左值
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: