C++中的const用法【02】----函数的参数和返回值
2015-01-26 21:47
260 查看
如果按值传递对象,它意味着传递的参数在函数中是不能被修改的。
如果按常量返回用户定义类型的对象的值,这意味着返回值不能被修改。
如果传递参数并返回地址,const 将保证改地址不会被改变。
1. 传递const 值
如果参数是按值传递,那么可用const 修饰指定参数。
这里有一个规定,就是value2已被const 修饰,在fun1()函数的整个生命周期中,value2都无法被修改。由于采用的是按值传递,因此fun1()在这里会定义2个实参的副本作为形参,并将第二个形参设置为const 对象。
const 在函数中的用法很简单,就是将一个对象修饰成“无法被修改的”,因此可以将它试做被调的工具而非主调的。(因为上述过程对于主调来说是不知情的)
为了使得程序更加清晰,最好将const 限定参数放在函内部而非它的参数列表,这样可以使得被调的形参列表与主调相同。
我们可以借助引用,让const 限定参数这一过程在函数内部实现,但需要注意的是,在内部实现的情况下,我们定义的引用变量是const 的,但形参依然是非const ,这意味着形参依旧可以被改变。因此,我们一旦使用了引用去实现,在接下来的描述中,要尽量使用const 修饰的引用变量而非原参数。
2. 返回const 值
对函数的返回值而言,const 也有类似的功能:将一个函数的返回值限定为常量。
其声明形式如下:
这样的形式会使得函数框架中原变量不会修改。
对于内建类型(int , double , char等)而言,按值返回的对象是否是一个const ,都无关紧要,因为它返回的是仅仅一个值,就如同
一样,是一个简单的赋值过程,因此对于主调的接收值类型来说,有没有const 都可以。但在没有必要时最好不要带上,不然容易引起混淆。
而当处理用户自定义的类型(struct,class)时,按值返回常量却是非常重要的,如果一个函数按值返回一个类类型的const 对象时,那么这个函数的返回值就不能作为一个左值(即不能出现在等号左边,不能被赋值或被修改)
总结:在按值传递内建类型时,const 没有意义的原因是,编译器已经成功的阻止它成为左值,因为这样的函数返回的是一个值,而不是一个变量,一个值只能被其他对象接收,而不能被更改。因此,只有按值返回一个用户定义的类类型时,const 的修饰才会变得不可或缺。
3. 传递和返回地址
如果传递或返回一个地址,那么其处置可能被通过操纵地址所改变,使用const 修饰可以有效的阻止这类事情的发生。并且,无论什么时候将地址传递给函数,都英爱尽可能的使用const 去限制。
如果按常量返回用户定义类型的对象的值,这意味着返回值不能被修改。
如果传递参数并返回地址,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 ; }
相关文章推荐
- [C/C++] const 详解(修饰变量、输入参数、返回值、成员函数)
- C/C++的区别(默认值、内联函数、函数重载、const、引用、参数、返回值)
- [C/C++] const 详解(修饰变量、输入参数、返回值、成员函数)
- [C++] C++中const修饰指针,变量, 函数参数和函数返回值的用法总结
- c++ const: const 变量, const 输入参数, const 返回值, const 成员函数
- const 修饰函数参数,返回值,函数体
- C++ const 参数 成员函数 规则
- c/c++的函数参数与返回值
- C++变长参数函数的用法(转)
- C++中的const成员函数(函数声明后加const,或称常量成员函数)用法详解
- C++ 函数返回值声明为const的原因
- C++变长参数函数的用法(转)
- const限定修饰符用法总结(常量,指针,迭代器,函数参数,成员函数)
- [收藏]C++ Tips(9)--函数参数中的const
- 【转载】const用法详解,如何修饰变量,返回值以及成员函数
- C++ 函数返回值声明为const的原因
- C++函数参数和返回值三种传递方式
- C++函数参数和返回值三种传递方式:值传递、指针传递和引用传递(着重理解)
- C++变长参数函数的用法(转载)
- C++函数参数中的省略号用法分析