《C++ Primer》读书笔记第六章-1-函数基础 And 参数传递

笔记会持续更新,有错误的地方欢迎指正,谢谢!

前言:先介绍函数的定义和声明,参数传递和函数返回;重载函数:几个不同的函数用同一个函数名,匹配调用:调用的是哪个;最后介绍函数指针。本章有意思,一起吃鸡吧!

函数基础

遇到一条return语句时,结束执行过程,return语句完成两项工作:
1.返回return语句中的值
2.将控制权还给主调函数

局部对象

局部静态对象:不同于只存在于块执行期间的自动对象,局部静态对象直到程序终止才被销毁;没有显式初始值时会执行值初始化。
static int cnt = 0;

函数声明

制造一次,使用多次。
函数的声明和函数的定义非常类似,唯一的区别就是函数声明无须函数体:
int fact(int val);

分离式编译

c++开发中广泛使用声明和实现分开的开发形式,其编译过程是分离式编译,就是说各个cpp文件完全分开编译,然后生成各自的obj目标文件,最后通过连接器link生成一个可执行的exe文件。
注意:定义函数的源文件还要把含有函数声明的头文件包含进来,目的是:编译器来验证函数的定义和声明是否匹配。
例子:

--test.h--
  void fun();//这里的.h文件只是声明一个函数
--test.cpp--
  #include ”test.h”
  void fun()//这里给出了test.h中声明的f函数的具体实现
  {
     std::cout<<"分离式编译"<<std::endl;
  }
--main.cpp--
  #include ”test.h”
  int main()
  {
   fun(); //调用fun
  }

参数传递

形参的类型决定了形参和实参交互的方式:
1. 形参为值类型:形参和实参是两个独立的对象,只不过是实参的值拷贝给形参了。
2. 形参为引用:形参绑定到实参上,形参就是实参的绰号,是同一个。

传值参数

形参为值类型,形参的变化不会影响实参,因为经过了一次拷贝。若想要影响实参,就用返回值呗,不过要经过两次拷贝咯。

指针参数

对指针参数也同理:

void reset(int *p)
{
    *p=0;//通过指针来改变值,对i有效!
    p=0;//改变的是副本,对&i无效!要想有效,形参就用二级指针。
}
int main()
{
    int i=666;
    cout<<i<<endl;
    cout<<&i<<endl;
    reset(&i);
    cout<<i<<endl;
    cout<<&i<<endl;
    return 0;
}

传引用参数

例子1:

void reset(int &i) //引用形参
  i = 0;

例子2:

bool isShorter(const string &s1, const string &s2) //为什么用const,参数不用改变时,尽量都用它。
{
  return s1.size() < s2.size();
}

总结:使用引用可避免拷贝操作。

const形参和实参

void f(const int i){//省略}
void f(int i){//省略}//错误,重复定义!

总结:实参初始化形参时会忽略顶层const,所以有无顶层const版本等价(上述两种的实参类型都可为int型或const int型,但第一个的形参不可被改变,第二个可被改变),都定义则属于重复定义!

指针形参或引用形参 与const
void reset(int *p){} //
void reset(int &p){} //重载函数
int main()
{
  int i = 42;
  const int ci = i;
  reset(&i); //正确:调用第一个函数
  reset(&ci); //错误:p不能指向常量const。实参不能初始化int*变量,可初始化const int*变量。
  reset(i); //正确:调用第二个函数
  reset(ci); //错误:不能把引用p绑定到常量const上。实参不能初始化int &变量,可初始化const int&变量。
}
尽量使用常量引用

对于引用来说,只要不需改变形参的值,都尽量用常量引用,理由有两点:

  1. 该用常量而不用常量,会让函数的调用者认为函数可以改变它的实参的值;
  2. 非常量引用会限制函数所能接受的实参类型。刚刚就学过,我们不能把const赋给非const,但可以把非const的给const。

数组形参

当函数不需要对数组元素执行写操作时,数组的形参应该是指向const的指针;
只有当函数确实要改变元素值得时候,才把形参定义成指向非const的指针。

数组引用形参

//这里的10形参,是数组类型的一部分,所以只接受10个元素的数组。

void fun(int (&arr)[10])
{
    for(auto elem : arr)
    {
        cout << elem << endl;
    }
}
含有可变参数的函数

有时候我们不清楚应向函数传递几个实参(不同类型/同类型),则可传递一个名为initializer_list的标准库类型。

PS:后面只是举例,看不下去的同志可以不往下看啦~

例子:我们要写一个输出错误的程序,我们不知道有多少错误,但这些错误的类型都是string。

void errorMsg(initializer_list<string> il)//同类型时
{
 for(auto beg = il.begin(); beg != il.end(); ++beg)
 {
     cout << *beg << endl;
 }
}

我们可以用不同的参数数量去调用:
errorMsg({"aaa","a","b"});//向initializer_list传递值序列要用花括号
errorMsg({"a", "b"});//不同数量的实参

还可以加其他类型的参数,加上就行了。
void errorMsg(int a, initializer_list<string> il){}//不同类型时

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值