C++ primier(四)

(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的元素是对应初始值的副本,列表中的元素是const
lst2(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指向lengthCompare
pf = &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作用于某个函数时,返回函数类型而非指针类型,需要显示加*

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值