c++ primer 阅读手记 第六章
1、函数返回类型:不能是数组类型或函数类型,但可以是指向数组或函数的指针。
2、自动对象:只存在于块执行期间的对象。比如:函数形参
3、局部静态对象:程序执行路径第一次经过对象定义语句时初始化,并且程序终止才被销毁,即使对象所在的函数结束执行也不会对它有影响。
如果局部静态变量没有显示的初始化,它将执行值初始化,内置类型的局部静态变量初始化为0。
4、类似于变量,函数只能定义一次,但可以声明多次;
extern int j; //声明变量j
int j; //声明并定义j
void print(int i,int s) { /* 函数体 */ } //函数定义
void print(int i,int s); //函数声明,注意分号
void print(int,int); //函数声明可以省略形参名字,但不建议
函数三要素(返回类型、函数名、形参类型)描述函数接口。
5、分离式编译
6、指针形参:指针的行为和其他非引用类型一样。可改变指针所指向的值,但指针本身拷贝,是两个不同的指针。
7、传引用参数:避免拷贝操作,优化效率,且有些对象不支持拷贝。
8、函数形参初始化,与变量初始化类似;可以理解为:
void fcn(const int i) {/* fcn能够读取i,但不能向i写值*/}
//既可以传入const int 也可以传入 int,忽略掉形参的顶层const。
//int x = 10;
//fcn(x); 调用函数时,形参初始化,个人理解:const int i = x;
//引用形参:void ff(int &s) {}
//ff(x); 调用函数时,形参初始化,个人理解:int &s = x;
void fcn(int i) {/* ... */} //错误:重复定义fcn(int)
int &r4 = 42; //错误:不能用字面值初始化一个非常量引用
9、数组形参
数组不支持拷贝、数组通常转换成指针;
//尽管形式不同,但完全等价,加const则对传入的数组不执行写的操作
void print(const int*);
void print(const int []);
void print(const int [10]); //数组元素个数10,只做标识
//每个函数都有const int*类型的唯一形参
int i = 0, j[2] = {1,2};
print(&i);
print(j);
//考虑数组元素数量的两种定义
void print(const int *beg, const int *end) {}
print(begin(j),end(j));
void print(const int ia[], size_t size) {}
print(j, end(j) - begin(j));
//数组引用形参
f(int &arr[10]) //错误,将arr声明成了引用的数组,并不存在
f(int (&arr)[10]) //正确,arr是具有10个整数的整型数组的引用
//传递多维数组:和所有数组一样,传递指向数组首元素的指针
//多维数组本质上是数组的数组,首元素本身就是一个数组,需要传递的就是指向数组的指针
//数组的第二维的大小是数组类型的一部分,不能省略
//matrix指向数组的首元素,该数组由10个整数构成
void print(int (*matrix)[10],int rowSize) {/*...*/}
//int *matrix[10]; //10个指针构成的数组,所以上面的括号不可少
//等价定义
void print(int matrix[][10],int rowSize) {/* ... */}
//main:处理命令行选项
int main(int argc, char *argv[]) {...}
//第二个形参 argv就是指针构成的数组,第一个形参argc是字符串的数量
//等价定义,argv指向char*
int main(int argc, char **argv) {...}
10、含有可变形参的函数:函数传递的实参数量不确定
C++11新标准有两种方法:a、如果所有实参类型相同,可以传递一个名为initializer_list的标准库类型;b、如果实参类型不同,编写一种特殊的函数,即可变参数模板。
C++还有一种特殊的形参类型(即省略符),可以传递可变数量的实参。
initializer_list和vector一样,也是模板类型;
initializer_list<string> ls;
initializer_list<int> li;
和vector不一样的是:initializer_list对象中的元素永远是常量值,不可改变;
省略符形参应该仅仅用于C和C++通用的类型。特别注意,大多数类型的对象在传递给省略符形参时都无法正常拷贝。
11、值是如何被返回的
返回一个值的方式和初始化一个变量或形参的方式完全一样:返回的值用于初始化调用点的一个临时量,该临时量就是函数调用的结果。
12、不要返回局部对象的引用或指针
13、主函数main的返回值:0表示执行成功
14、递归函数
15、返回数组指针
16、三种函数相关的语言特性:默认实参、内联函数、constexpr函数
默认实参:string screen(sz ht = 24, sz wid = 80, char backgrnd = ' ');
调用只能省略尾部实参:
window = screen(, , '?'); //错误
window = screen(30);//等价于screen(30,80,' ');
重复声明函数,不能修改已经存在的默认值,但可以添加默认值;
内联函数:在函数返回类型前面加关键字inline,节省开销,编译器可忽略。
constexpr函数:能用于常量表达式的函数。函数的返回值类型及所有形参类型都是字面值类型,函数体有且只有一条return语句。
constexpr int new_sz() { return 42; }
constexpr int foo = new_sz(); //正确:foo是一个常量表达式
constexpr函数被隐式地指定为内联函数;
constexpr函数不一定返回常量表达式。
内联函数、constexpr函数 通常定义在头文件中。
17、函数指针
函数的类型由它的返回类型和形参类型共同决定,与函数名无关。
bool (*pf)(int i, int j); //未初始化,返回bool类型的函数指针
bool *pfd(int i, int j); //返回bool类型指针的函数
指向不同函数类型的指针不存在转换规则,函数类型不匹配不可指向;
pf = 0;
pf = nullptr;
//调用 pf = 函数名;等价 pf = &函数名; &可选
函数指针可作为函数的形参;