C++ primier(四)

来源:互联网 发布:linux shell usleep 编辑:程序博客网 时间:2024/06/10 21:05

(35)自动对象,只存在于快执行期间的对象成为自动对象

当块的执行结束后,块中创建的自动对象的值就变成未定义了。

形参是一种自动对象,函数开始时为形参申请存储空间,一旦函数终止,形参就被销毁

(36)局部静态对象:有时候,有必要令局部变量的声明周期贯穿函数调用及之后的时间。局部变量在程序的执行路径第一次经过对象定义语句时初始化,直到程序终止时才被销毁

size_t count_calls(){    static size_t ctr = 0;     return ++ctr;}int main(){    for(size_t i=0;i!=10;++i)         cout<<count_calls()<<endl;     return 0;}


(37)使用引用避免拷贝

拷贝大的类类型或者容器对象比较低效,甚至有的类类型不支持拷贝操作,函数通过引用形参访问该类型的对象。

当无需修改引用形参的值最好使用常量引用。

//比较两个string 因为string可能会非常长,所以尽量避免直接拷贝他们,这时引用形参是比较明智的选择bool isShorter(const string &s1,const string &s2){     return s1.size()<s2.size();}

使用引用形参返回额外信息

尽量使用常量引用,把不会改变的形参定义成普通的引用是一种比较常见的错误,这么做带给函数的调用者一种误导,即函数可以修改它的实参的值。此外,使用引用儿非常量也会极大地限制函数所能接受的实参类型。因为我们不能把const,字面值或者需要类型转换的对象传递给普通的引用形参。

例如

string::size_type find_char(string &s,char c,string::size_type &occurs)

只能将find_char作用于string,类似于find_char("hello world",'o',ctr)会在编译时发生错误



数组形参,数组的两个特殊性质对我们定义和使用在数组上的函数有影响,两个性质分别是:1不允许拷贝数组,2使用数组时通常会转换成指针

因为不能拷贝数组,所以无法以传值的形式的方式使用数组参数,数组会转换成指针,所以使用函数传递一个数组时,实际上传递的是指向数组元素的首指针

传递多维数组

void print(int(*matrix)[10],int rowsize)


(38 )initializer_list:如果函数的实参数量未知,但是全部实参的类型相同,我们可以使用initializer_list类型的形参,其定义在同名的文件中

//initializer_list提供的操作initializer_list<T> lst;initializer_list<T> lst{a,b,c};//lst的元素数量和初始值一样多,lst的元素是对应初始值的副本,列表中的元素是constlst2(lst);lst2=lst;lst.size();lst.begin();//返回指向lst中首元素指针lst.end();

例子

void error_msg(initializer_list<string> il){     for(auto beg = il.begin();beg!=il.end();++beg)          cout<<*beg<<" ";     cout<<endl;}

(39)省略符形参,为了便于c++访问某些特殊的c代码设置的

(40)有返回值的函数

例子

string make_plural(size_t ctr, const string &word,const string &end){     return (ctr>1)?word+end:word;}

该函数返回值是string,意味着返回值将被拷贝到调用点。因此该函数返回word的副本或者一个未命名的临时string对象,该对象的内容是word和endd的和


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

例子

const string &manip(){     string ret;     if(!ret.empty())          return ret;     else          return "Empty";}

以上两条return都讲返回未定义的值,第一条return显然返回局部变量的引用,第二条,将字符串字面值转换成一个局部临时string对象,对于manip来说,该对象和ret一样是局部的。当函数结束时,临时对象占用的空间也就随之释放,所以两条return指向了不在可用的内存空间。指针同理。


返回数组指针,因为数组不能被拷贝,所以函数不能返回数组,不过函数可以返回数组的指针或引用。但在语法上比较繁琐,因此,可以有一些方法简化

typedef int arrT[10];// arrT是一个类型别名,表示类型是含有10个整数的数组using arrT = int[10];arrT*func(int i);

不使用类型别名,必须牢记定义名字后面数组的维度

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

C++11中还引入了尾指针返回法,简化

auto func(int i)->int(*)[10];

(41)函数指针

bool lengthCompare(const string&,const string &);//函数类型为bool (const string&,const string&)bool (*pf)(const string &,const string &);//未初始化pf = lengthCompare;//pf指向lengthComparepf = &lengthCompare;//等价的


此外 还可以直接使用指向函数的指针调用该函数,无需提前解引用指针

bool b1=pf("hello","goodbye");bool b2 =(*pf)("hello","goodbye");//等价调用bool b3 = length("hello","goodbye");

函数指针形参

void useBigger(const string &s1,const string &s2,bool pf(const string&,const string &));//等价的声明:显示的将形参定义成指向函数的指针void useBigger(const string &s1,const string &s2,bool (*pf)(const string &,const string &))
使用类型别名和decltype简化

typedef bool Func(const string &,const string &)typedef decltype(lengthCompare) Fun2;//等价的类型//FuncP和FuncP2是指向函数的指针typedef bool(*FuncP) (const string &,const string &);typedef decltype(lengthCompare) *FuncP2;

返回指向函数的指针

和数组相似,不能返回一个函数,但是可以返回指向函数类型的指针。

直接

int (*f1(int)) (int *,int);

使用别名

using F = int (int*,int);F f1(int);//错误F *f1(int);//正确using PF = int(*)(int *,int);PF f1(int);

使用尾指针

auto f1(int) ->(*)(int *,int);

使用decltype

string::size_type sumLength(const string&,const string &);

decltype(sumLength) *getFcn(const string &);

decltype作用于某个函数时,返回函数类型而非指针类型,需要显示加*

原创粉丝点击