局部静态变量,关键字static修饰,即使函数结束执行也不受影响,生存期直到程序终止。
java中static的单一存储空间的概念与其或有异曲同工之妙。
函数的形参可以无名,但有名可以使其意义更加清晰。
分离式编译的一种模式:头文件中声明函数,在name.cpp文件中定义,最后在name_main.cpp中实现
若函数传值调用,则实参和形参为两个独立的个体;若函数传引用调用,形参为实参的别名,即同一个体
形参为指针:
例如:void reset(int *p){
*p=0;//解引用改变所指对象的值
}
int i=24;
reset(&i);//此时i==0
形参为引用:
例如:void reset(int &p){
p=0;}//p所引用的对象的值被改变
int j=24;
reset(j);//此时j==0,reset内部对 p 的操作即为对 j 的操作
如果类类型过大或者就不支持拷贝,则需要以引用为函数形参(如果不希望改变对象的值,参数类型应为const)
另外传引用可以获得额外信息,在函数使用完毕后,传入的参数其值保留
若函数的形参为顶层const,传入非const参数作为实参是允许的(此时顶层const被忽略,故仅仅有无const不能重载函数)
与上一条相对地,若形参为非常量,则禁止传入常量实参
若非必要,引用型形参尽量是常量引用,若函数嵌套调用时内外层引用形参不同为常量/非常量,易引发错误
例如:void func1(const string &s){
/*…………………….*/
func2(/*string*/ s);}//此例即不通
数组形参:
例如:void func(const int*);
void func(const int [ ]);
void func(const int [10]);//仅表示希望的元素个数,实际调用不一定,与前两条等价
防止越界的操作:
例如:void print(const char *cp){
if(cp)//非空指针
while(*cp)//非空字符
cout<<*cp++;}//向后位移
也可:void print (const char *beg,const char *end){//end是尾后元素
while(beg!=end)//输出不含end的所有元素,end可由end(arr)获取,begin可由begin(arr)获取
cout<<*beg++;}
也可:void print (const int ia[ ],size_t size){
for(size_t i=0 ; i != size; i++){
cout<<ia[ i ];}//显式固定大小
数组引用形参:
例如:void print( int (&arr)[10]){//注意括号位置
for(auto elem:arr)
cout<<elem;}//不足是大小固定
多维数组形参:
例如:void print( int (*matrix)[10], int rowsize){/*………….*/}
处理命令行选项时,main函数需要参数:int main(int argc,char* argv[ ])
可变形参:
initializer_list形参:(形参数目未知,类型相同)
initializer_list
默认初始化,T类型空列表
initializer_list
const T 类型元素与lst列表中数量相同,是对应初始值的副本
lst2(lst)或lst2=lst
拷贝或赋值initializer_list对象,但不赋值列表中的元素,原列表和副本共享元素
lst.size()
列表元素数量
lst.begin()
指向lst首元素的指针
lst.end()
指向lst尾后元素的指针
例如:void print(initializer_list
for(auto beg=lst.begin();beg!=lst.end();beg++)
cout<<*beg; }
print({"FunctionX","Okey"});//调用时必须带花括号
省略符形参:(并不好用,传递参数容易出错)
例如:void foo(int,…);
void foo(…);//省略符必须在参数列表末尾
返回值和return:
不要返回局部对象的指针或引用(函数完成后,局部对象就已经不存在了)
调用一个返回引用的函数得到左值,其他返回类型得到右值。
c++11允许返回一组花括号括起来的列表(列表初始化返回值),若为内置类型列表内仅能包含最多一个值:
例如:vector
/*……….*/return{};
/*……….*/return{"Hello","World"}; }
返回数组指针(指向数组的指针):(如果不想使用类型别名,定义的名字后面数组的元素个数要记住)
例如: int(*func(int i))[10];
尾置返回类型(c++11):像是返回数组指针或者数组引用之类的复杂类型较为合适,当然所有类型返回值都可用
例如:auto func(int i)->int(*)[10];(得到了与上一条相同的效果,而且更加清晰)
使用decltype(c++11):(已知返回的指针指向哪个数组)
例如:int odd[ ]={1,3,5,7,9};
int even[ ]={2,4,6,8,10};
decltype(odd) *func(int i){//注意此处*不能省
return (i%2)?&odd:&even;}
仅仅返回类型不同不能构成重载函数,函数的形参列表是否为顶层const并无区别,然而形参是否为底层const对函数确有影响
如chap4所示,const_cast
注意:名字查找在类型查找之前(局部作用域内的新声明会覆盖外层同名对象,导致内部调用时引发错误)
在函数声明的形参列表中可以提供默认值(要么所有形参都有默认值,要么就都没有):
例如:string screen(size_type ht=24,size_type wid=80,char background=' ');
screen();//等价于screen(24,80,' ');
screen(44);//等价于screen(44,80,' ');
screen(22,88);//等价于screen(22,88,' ');
也就是说,提供的值必须是按照声明顺序的,调用screen('?');等价于screen('?',80,' '); 显然不合法
内联函数inline:声明函数之前加上inline关键字,可以使其调用更快(至于内联是否生效看编译器是否批准内联请求,通常用于结构较为简单的函数)
constexpt函数:函数的返回值类型及所有形参的类型都是字面值类型,而且函数体中必须有且只有一条return语句;
如果调用实参为常量,返回常量表达式,调用非常量,返回的也非常量(使用此函数在定义函数前加上constexpr关键字)
通常内联函数和constexpr函数被定义在头文件中(因为允许此两种函数在程序中多次定义)
assert预处理宏(断言):(#include
例如:assert(expression);//expression==true,assert什么也不做;expression==false,程序终止并返回信息
处理调试状态:
定义预处理变量NDEBUG:#define NDEBUG:关闭调试状态(此举可使assert无效)
除了使用assert,也可以自定义条件调试代码:
void print(const int ia[ ],size_t size){
#ifndef NDEBUG
cerr<<__func__<<":array size is "<<size;
#endif}
__func__存放函数名字的字符串字面值(这里输出当前调试的函数名)
__FILE__存放文件名的字符串字面值
__LINE__存放当前行号的整型字面值
__TIME__存放文件编译时间的字符串字面值
__DATE__存放文件编译日期的字符串字面值
函数指针:指向的是函数而非对象
例如:bool lengthCompare(const string&,const string&);
bool (*bf)(const string&,const string&);//要求返回类型和形参类型及数量完全一致
bf =0;//表示不指向任何函数
bf=&lengthCompare;(或bf=lengthCompare;)//bf指向函数lengthCompare
bf("Hello","World");(或(*bf)("Hello","World");)//利用bf调用函数lengthCompare,无须提前解引用指针
void usePointer(const string&,const string&,bf(const string&,const string&));//这里usePointer函数的第三个参数是函数指针,与上面的bf相同性质
使用类型别名表示返回类型式函数指针:尾置返回类型也可(auto f1(int)->int(*)(int* ,int))
using PF=int(*)(int*,int);//PF是指针类型 PF f1(int);
using F=int (int* ,int);//F是函数类型 F *f2(int);//显式地表示返回函数指针,*不能省
r若已知返回的函数是哪个:
int func1(const int&,const int&);
int func2(const int&,const int&);
decltype(func1) *usefcn(const int&);//注意此处*不能省,decltype得到的是函数类型
//本章概念较为混乱,需多看多记
手机扫一扫
移动阅读更方便
你可能感兴趣的文章