C++primer读书笔记(第六,七章)

来源:互联网 发布:kali linux卸载输入法 编辑:程序博客网 时间:2024/05/16 17:59

第六章 语句

1.简单语句

case标号必须是整型常量表达式

case 3.14;         //noninteger

case ival;            //nonconstant

第七章  函数

1.参数传递

可以将指向const对象的指针初始化为指向非const对象,但不可以让指向非const对象的指针指向const对象

复制实参的局限性:不适合复制实参的情况包括

a.当需要在函数中修改实参的值时

b.当需要以大型对象作为实参传递时,对实际的应用而言,复制对象所付出的时间和存储空间代价往往过大

c.当没有办法实现对象的复制时

使用引用形参,函数可以直接访问实参对象,而无须复制它。

如果使用引用形参的唯一目的是避免复制实参,则应将形参定义为const引用。

非const引用形参只能与完全同类型的非const对象关联。

应该将不修改相应实参的形参定义为const引用,如果将这样的形参定义为非const引用,则毫无必要的限制了该函数的使用。

数组有2个特殊的性质,影响我们定义和使用作用在数组上的函数:

a.不能复制数组

b.使用数组名时,数组名会自动转化为指向其第一个元素的指针。

当编译器检查数组形参关联的实参时,它只会检查实参是不是指针,指针的类型和数组元素的类型是否匹配,而不会检查数组的长度。

通过引用传递数组

void printVlaues(int (&arr)[10])

{

for(size_t i=0;i!=0;++i)

cout<<arr[i]<<endl;

}

&arr两边的圆括号是必须地,因为下次奥操作符具有更高的优先级:

for(int &arr[10])                //error:arr is an array of reference

for(int (&arr)[10])              //ok:arr is a reference to an array of 10 ints

int *matrix[10];                //array of 10 pointers

int (*matrix)[10];              //pointer to an array of 10 ints

2.return 语句

返回类型是void的函数使用return是为了引起函数的强制结束,如

void int()

{

return;

}

返回类型是void的函数还可以返回另一个返回类型同样是void的函数的调用结果。如

void swap(int a,int b)

{

return do_swap(a,b);

}

在含有return语句的循环后没有提供return语句是很危险的,因为大部分的编译器不能检测出这个漏洞,运行时会出现什么问题是不确定的。

关于main函数的返回值,其返回值独立于机器,在vstdlib头文件中定义了2个预处理变量,分别表示程序运行的成功和失败:

#include <cstdlib>

int main()

{

if(some_failure)

return EXIT_FAILURE;

else

return EXIT_SUCCESS;

}

返回非引用类型:函数的返回值用于初始化在调用函数处创建的临时对象。

返回引用:当函数返回引用时,没有复制返回值,而是直接返回对象本身。且返回引用的函数返回一个左值。如果不希望返回值被修改,返回值应该声明为const。

const char & get_val();

返回引用至关重要的是:千万不要返回局部变量的引用。

3.函数声明

在头文件中提供函数声明,定义函数的源文件应包含声明该函数的头文件

函数调用的实参按位置解析,默认实参只能用来替换函数调用缺少的尾部实参

默认实参可以是任何适当类型的表达式,在一个文件中,只能为一个函数指定默认实参一次

4.内联函数

const string &shorterString(const string& s1,const string &s2)

{

return s1.size()<s2.size()?s1:s2;

}

为这样一个小操作定义一个函数的好处是:

a.阅读和理解函数shorterString的调用,要比读一条用等价的条件表达式取代函数调用表达式并解释他们的含义要容易的多

b.如果需要做任何修改,修改函数要比找出并修改每一次等价表达式容易的多

c.使用函数可以确保统一的行为,每个测试都保证以相同的方式实现

d.函数可以重用,不必为其他的应用重写代码

将shorterString写成函数有一个潜在的缺点:调用函数比求解等价表达式要慢的多

内联函数避免函数调用 的开销,在函数返回类型前面加上关键字inline就可以将shorterString函数指定为内联函数,内联函数通常就是将它在程序中每个调用点上“内联地”展开

一般来说内联机制适用于优化小的,只有几行的而且经常被调用的函数,大多数的编译器都不支持递归调用的内联函数,内联函数应该在头文件中定义,这一点不同于其他函数。

5.类的成员函数

编译器隐式的将在类内定义的成员函数当做内联函数,类的成员函数可以访问类的private成员。

每个成员函数(除了static成员函数外),都有一个额外的,隐含的this指针,在调用成员函数时,形参this初始化为调用函数的对象的地址。

const对象,指向const对象的指针或者引用只能调用其const成员函数,如果尝试用他们来调用非const成员函数,则是错误的。

6.重载函数

出现在相同作用域中的两个函数,如果具有相同的名字而形参表不同,则成为重载函数

任何程序都仅有一个main函数的实例,main函数不能重载

如果两个函数的形参表完全相同,但返回类型不同,则第二个声明是错误的

有const引用形参的函数与有非const引用形参的函数是不同的,类似的,如果函数带有指向const类型的指针形参,则与带有指向相同类型的非const对象的指针形参的函数不相同

一般来说,局部的声明函数是一种不明智的选择,函数的声明应该放在头文件中。在c++中名字查找发生在类型检查之前。

重载和const形参:仅当形参是引用或者指针时,形参是否为const才有影响

7.指向函数的指针

bool (*p)(const string &,const string&);

*p两侧的圆括号是必须的

bool *p(const string&,const string& );           //declares a functong named pf that returns a bool*

用typedef简化函数指针的定义

typedef bool (*cmpFcn)(const string&,const string&);

在要使用这种函数指针类型时,只需要直接用cmpFcn即可,不必把整个类型声明全部写出来

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

 

cmpFcn pf1=0;                     //OK::unbound pointer to function

cmpFcn pf2=lengthCompare;                //OK:pointer type matches function's type

pf1=lengthCompare;             //OK:pointer type matches function's type

pf2=pf1;                                 //OK:pointer types match

此时,直接引用函数名等效于在函数名上应用取地址符;

cmpFcn pf1=lengthCompare;

cmpFcn pf2=&lengthCompare;

 

函数指针只能通过同类型的函数或者函数指针或者0值常量表达式进行初始化赋值

 

可以不需要使用解引用操作符,直接通过指针调用函数;

cmpFcn pf=lengthCompare;

lengthCompare("hi","bye");

pf("hi","bye");

(*pf)("hi","bye");