C++Primer:函数(参数传递-非引用形参)
2016-06-03 15:55
375 查看
1.参数传递
每次调用函数时,都会重新创建该函数所有的形参,此时所传递的实参将会初始化对应的形参。形参的初始化与变量的初始化一样;如果形参具有非引用类型,则复制实参的值,如果形参为引用类型,则他只是实参的别名。
2.非引用形参
普通的非引用类型的参数通过复制对应的实参实现初始化。当用实参副本初始化形参时,函数并没有访问调用所传递的实参本身,因此不会修改实参的值。非引用形参表示对应实参的局部副本。对这类形参的修改仅仅改变了局部副本的值。一旦函数执行结束,这些局部变量的值也就没有了。
2.1 指针形参
函数的形参可以是指针,此时将复制实参指针。与其他非引用类型的形参一样,该类形参的任何改变也仅作用于局部副本。如果函数将新指针赋给形参,主调函数使用的实参指针的值没有改变。事实上,被复制的指针只影响对指针的赋值。如果函数形参是非const类型的指针,则函数可通过指针实现赋值,修改指针所指向对象的值。
<span style="font-size:18px;">#include <iostream> using std::cout; using std::endl; void Reset(int* ip); int main() { int i = 100; int* p = &i; cout<<"Befor"<< *p<<endl; Reset(p); cout<<"After"<<*p<<endl; return 0; } void Reset( int* ip) { *ip = 0; ip = 0; }</span>上述程序运行结果为 100,0;
解释:调用reset后,实参依然保持原来的值(指的是指针的名字,而非指针指向的内容),但是它所指向的对象的值将变为零。
如果保护指针指向的值,则形参需定义为指向const对象的指针:
#include <iostream> using std::cout; using std::endl; void Reset(const int* ip); int main() { int i = 100; int* p = &i; cout<<"Befor"<< *p<<endl; Reset(p); cout<<"After"<<*p<<endl; return 0; } void Reset(<strong><span style="color:#3333ff;">const</span></strong> int* ip) { <span style="color:#ff6666;"><strong>*ip = 0;</strong></span> //error:不能给指向const int类型的指针赋值 ip = 0; }指针形参是指向const类型还是非const类型,将影响函数调用所使用的实参。我们既可以用int*也可以用const int*类型的实参调用Reset()函数;但仅能将int*类型的实参传递给Reset函数。这个差别来源于指针的初始化规则:
可以将指向const对象的指针初始化为指向非const对象;
<p><span style="font-family: Arial, Helvetica, sans-serif;">i = 100;</span></p>const int* cip = &i; //OK:This is Right但不可以让指向非const 对象的指针指向const对象;
const int i = 100; int* ip = &i; //error C2440: “初始化”: 无法从“const int *”转换为“int *”
2.2 const形参
在调用函数时,如果该函数使用非引用的非const形参,则既可以给该函数传递const实参,也可以传递非const的实参。例如:
int gcd(int v1, int v2) // 求最大公约数 { while(v2) { int temp = v2; v2 = v1 % v2; v1 = temp; } return v1; } int main() { const int i = 3, j = 6; int k = gcd(3,6); //OK,k initialized to 3 }
这种行为源于const对象的标准初始化规则。因为初始化复制了初始化式的值,所以可用const对象初始化非const对象,反之亦然。
如果将形参定义为非引用的const类型:
void fcn(const int i) { /* fcn can read but <strong><span style="color:#ff0000;">not write to i</span></strong> */ }
则在函数中,不可以改变实参的局部副本。由于实参仍然是以副本的形式传递,因此传递给 fcn 的既可以是 const 对象也可以是非
const 对象。
3. 复制实参的局限性
复制实参并不是在所有的情况下都合适,不适宜复制实参的情况包括:1.当需要在函数中修改实参的值时;
2.当需要以大型对象作为实参传递时。对实际的应用而言,复制对象所付出的时间和存储空间代价往往过大;
3.没有办法实现对象的复制时。
对于上述几种情况,有效的解决办法是将形参定义为引用或指针类型。
相关文章推荐
- C++的tips(不定期更新)
- C/12个C语言面试题,涉及指针、进程、运算、结构体、函数、内存
- C++项目中的extern "C" {}
- C++之sizeof的用法
- C++ STL中Map的按Key排序和按Value排序
- C++虚继承的概念
- 关于c++指针
- 一段简单C++代码问题分析
- [置顶] c++ vector, set, map的用法总结
- C语言使用DP动态规划思想解最大K乘积与乘积最大问题
- POCO下的日志库封装成可以根据日期创建文件的单例类
- OpenCV 人脸识别 C++实例代码
- UNICODE 下CString与char*的相互转化
- C语言::将中缀表达式转换为后缀表达式并计算结果
- C++函数重载以及extern "C"
- 21天速成 C++?编程生涯的一点思考
- 【C】C语言ispunct()函数:判断字符是否为标点符号或特殊字符
- xapian简介<六>
- LeetCode 268: Missing Number
- c++中的常量折叠