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作用于某个函数时,返回函数类型而非指针类型,需要显示加*
- C++ primier(四)
- C++primier总结
- C++Primier笔记第一部分 基础
- C++ Primier读书笔记(第三章)
- C Primier Plus 第十三章 文件输入/输出
- C Primier Plus 第4章 字符串和格式化的输入/输出
- C Primier Plus 第5章 运算符、表达式和语句
- 《C++ Primier Plus》01
- 《C++ Primier Plus》02
- Efficient C++(四)
- C++(四)
- C语言(四)
- Unix C (四)
- Effective C++(四)
- C#(四)
- C练习(四)
- 《Effective C++》(四)
- C练习-(四)
- Coins
- RxJava2:observeOn和subscribeOn的使用
- Mybatis逆向工程,生成java、xml等文件
- 基于mysql Jdbctemplate 的上层封装,maven中央库可引用
- Leetcode——20. Valid Parentheses
- C++ primier(四)
- sp_addlinkedserver在存储过程中使用
- tomcat配置调优
- Android Studio 2.2.2的依赖库版本问题解决方案
- Android获取手机和系统版本等信息的代码
- 构建Spark分布式集群第一步:搭建Hadoop伪分布式环境
- 数字摘要和Hash函数(哈希函数)
- acpi_device_id 中cls的作用
- 图片解析框架