1. partone---第六章 函数

fig1.jpg

函数是一个命名了的代码块,可有0个或多个参数。


6.1 函数基础

局部对象

  • 自动对象: 存在于块执行期间,当块执行完毕时,则内存消失。例如函数的形参。
  • 局部静态对象: 生命周期为第一次定义到程序结束才终止。

函数声明

函数声明应该放到头文件中。 这样做的好处在于:同一函数的所有声明一致;想改变函数的接口,只需要改变函数的声明的即可。


6.2 参数传递

引用传递: 形参的类型决定了形参和实参的交互方式。 当形参是引用类型时,如其他引用一样,引用形参是对应实参的别名。
值传递: 将实参的值拷贝给形参,此时形参和实参是两个相互独立的对象。对形参的改变,不会影响到实参的值。

6.2.1 值传递

*指针形参

void reset(int *ip)
{
  *ip=0;
  ip=0;
}
int i=42;
reset(&i)

此时形参和实参是两个相互独立的对象。
实现两个数交换的两种方法(C++中,建议使用引用类型代替指针形参)

 void swap1(int *a,int * b)//指针 参数是两个指针变量
{
   int tmp;
   tmp=*a; //把a指向的值赋给tmp
   *a=*b;   //把b指向的值赋给a指向的值
   *b=tmp;   //把tmp的值赋给b指向的值
   //这样就达到了变换a,b指向的值的目的
 }
void swap2(int &a,int &b)//引用 参数是两个整型变量的引用
{
//引用就是他本身的值,所以直接交换两个的值就行了。
       int tmp;
       tmp=a;
       a=b;
       b=tmp;
}

6.2.2 引用传递

使用引用避免拷贝

当拷贝大的类类型对象或容器对象时,比较低效。

使引用可返回额外信息

一个return只能返回一个参数,通过引用带出多个参数。

6.2.3 const形参和实参

void fcn(const int i){};
void fcn(int i){};

上面这两个函数是一样的,不能重载。因为当形参有顶层const时,传给它的是const或非const均可以
顶层const:指针本身是一个常亮;
底层const:指针所指的对象是一个常量。

const  int ci=42;   //顶层const

指针或引用形参与const

非常量可以初始化一个底层const对象,反之则不行
同时,一个普通类型的引用,只能用同类型的对象初始化。

尽量使用常量引用

顶层const作为形参时,实参传递是const或非const均可;

例如:
bool  is_empty(string &s)
{
  return s.empty();
}

这种情况下,限制了该函数所能接受的实参类型,无法把const、对
象、字面值常量或者需要类型转换的对象传递给普通的引用形参。
另一方面,也可能带来误导,可修改字符串s。
应该把形参改为 const string &s

6.2.4 数组形参

数组的两个特性:不允许拷贝数组、数组名转换为指针

6.2.5 main:处理命令行选项

int main(int argc, char *argv[])
{
    //其中argc是argv[][]的行数
}

6.2.6 含有可变形参的函数---initializer_lsit

initializer_lsit是一种标准库类型。适用于函数的实参未知,但类型都相同的情况下。

int icount(initializer_lsit<int> il)
{
  int count =0;
  for(auto val :il)
  {
      count += val;
  }
  return count;
}
icount({1,2,3,4,5});

6.3 返回类型和return语句

6.3.1 无返回值函数

函数的返回类型是void时,如果函数末尾没有return时,也可以。因为在函数的最后一句会隐式的调用return

6.3.2 有返回值函数

return exp;

不要返回局部对象的引用或指针

函数终止后,局部变量的引用将不再指向有效的内存区域。

引用返回左值
char &get_val(string &str, int index)
{
    return str[index];
}

void main
{
  string s("a value");
  get_val(s,0) = 'A';  //改为 A value
}

6.3.3 返回数组的指针

int (*func(int i))[10];


6.4 函数重载

重载函数:名字相同,但是函数参数列表不同。
注:返回类型不算。

重载和const形参

顶层const
(因为当形参有顶层const时,传给它的是const或非const均可以)。

(因为当形参有顶层const时,传给它的是const或非const均可以),所以下面两组函数是重复声明。
Record lookup(phone);
Record lookup(const phone);

Record lookup(phone*);
Record lookup(phone* const );

形参是指针或者引用。将是底层const,可通过指向的对象时常量对象还是非常量对象实现重载。
一方面,const不能转换为其他类型,只能将const转换为const;另一方面,相反的,非const可以转换为const,但是当同时存在非常量和const两个版本的形参时,编译器会优先选择非常量版本的函数,

Record lookup(Account &);
Record lookup(const Account &);

Record lookup(phone*);
Record lookup(phone* const );

6.5 特殊用途语言特性

6.5.1 默认实参

规定:一旦某个形参被赋予了默认值,那么它后面的所有形参都必须被赋予默认值。

6.5.2 内联函数和constexpr函数

将函数指定为内联函数,通常就是在每个调用点进行展开。
constexpr函数---暂时用不到。

6.5.3 调试帮助

assert预处理

如:assert(expr),如果表达式为真,什么都不做;如果表达式为假,则输出信息并终止程序。

DEBUG 预处理命令

如果你把代码夹在#ifdef DEBUG 和对应的 #endif 中间,那么这段代码只有在调试(DEBUG)下才会被编译。也就是说,如果你在RELEASE模式下,这些代码根本就不会存在于你的最终代码里头。

 #include <iostream>
 using namespace std; 
 #ifdef DEBUG
 inline void msg()
{ 
 cout<<"I'm testing"; 
} 
 #else 
inline void msg() {} 
 #endif 
int main()
 {
   msg();
   return 0;
 }

6.6 函数匹配

背景:有几个重载函数,当一个调用函数调用重载函数时,可能会发生二义性。
解决办法:寻求最佳匹配。


6.7 函数指针

bool lengthCompare(const string &,const string &);

  1. 该函数的函数类型为bool lengthCompare(const string &,const string &)。 函数类型,是由形参列表和返回值决定,函数名称只是函数的别名而已。
  2. 声明一个函数指针,只需要使用指针代替函数即可(因为函数名称仅仅是一个别名)
    bool (*pf) (const string &,const string &)
  3. 如何使用函数指针
    当把函数名作为一个值使用时,该函数会自动的转换为指针。
    指向不同的函数指针之间,是不能转换的,因为代表的函数返回值。
pf = lengthCompare;   // 指向名为lengthCompare的函数
pf = &lengthCompare; //等价,取址操作符是可选的。

//直接使用
bool b1 = pf("hello", "world");
bool b2 = (*pf) ("hello", "world"); //等价调用
  1. 函数指针形参
//第三个形参是函数类型,自动转换为指向函数的指针
void useBigger(const string &, const string &, bool  pf (const string &,const string &));
|
void useBigger(const string &, const string &, bool  (*pf) (const string &,const string &)); //自动转换为函数指针

如上面,这样显得函数冗长。
通常:
typedef bool Func(const string &, const string &) ;
void useBigger(const string &, const string &, Func));

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容