C++11(5):函数

参数传递时,如果是引用类型,它将绑定到对应的实参上,否者,将实参的值拷贝后赋给形参。
引用可避免拷贝,如果不需要改变参数,最好定义成常量引用。
和其他初始化一样,当用实参初始化时会忽略顶层const,当形参有顶层const时,传给它常量对象或非常量对象都可以
我们可以用非常量初始化一个底层const对象,但反过来不行,同时一个普通的引用必须用同类型的对象初始化
尽量使用常量引用
可以使用数组引用形参f(int (&arr)[10]),来传输维度
对于多维数组,数组第二维的大小是组数类型的一部分,不能省略:
void print(int (*matrix)[10],int rowSize);
等价定义:   void print(int matrix[ ][10],int rowSize);
int main(int argc,char *argv[]);
为了处理不同数量的参数,有两种方法,
如果所有的参数类型相同,可以传递一个,initializer_list的标准库类型
如果实参的类型不同,我们可以使用可变参数模板
initializer_list提供的操作:
initializer_list<T> lst; //默认初始化
initializer_list<T> {a,b,c...}  //列表初始化
lst2=lst;   lst2(lst);    拷贝后原始列表和副本共享元素
lst.size()
lst.begin()
lst.end()
initializer_list对象中的元素永远是常量
void error_msg(initializer_list<string> il);
void error_msg(ErrCode e,initializer_list<string> il);
省略符形参是为了便于c++程序访问某些特殊的c代码而设置的。 
void foo(parm_lsit,...)   parm_list是正常的参数类型

千万不要返回局部变量的指针或引用
引用返回的是左值,因此可这样写 get_val(s,0) = 'A'
可以返回列表,类似于初始化;  return { };    return{"function","okay"};
main 的返回值在cstdlib中,EXIT_FAILURE,EXIT_SUCCESS;

因为数组不能拷贝,所以函数不能返回数组。不过可以返回数组的指针或数组的引用
typedef int arrT[10];等价于using arrT=int[10];
声明返回数组指针的函数
int (*func(int i))[10];
等价于,尾置返回类型  auto  func(int i)-> int(*)[10];
int odd[]={1,3,5,7,9};
int even[]={0,2,4,6,8};
decltype(odd) *arrPtr(int i);  
返回的是一个指向含有5个整数的数组的指针,decltype不负责把数组转换成指针

一个拥有顶层const的形参无法与另一个没有顶层const的形参区分开来
int lookup(phone);     int lookup(const phone);    重复声明
int lookup(one*);        int lookup(one * const);   重复声明
如果形参是指针或引用,区分其对象是const还是非const可以重载,此时是底层const
Record lookup(Account&);
Record lookup(const Account&);   可以重载
const对象不能转换成其他的类型,所以我们只能把const对象(或指向const的指针)传递const形参
相反,非常量可以转换成const,所以上述的两个函数都你作用于非常量和指向非常量对象的指针
当我们传递一个非常量,优先选用非常量版本函数
如果函数名字能区分并有一定意义  还是不要重载
可使用const_cast 来调用已有的函数实现const重载

c++名查找发生在类型检查之前,因此在局部中声明的名字会屏蔽之前的所以名字

函数可声明多次,后续声明只能为之前那些没有默认值得形参添加默认实参,而且该形参右侧的所有形参必须都有默认值 
string screen(sz,sz,char='  ');
string screen(sz,sz,char = '*');// 重复声明
string   screen(sz=3,sz=8,char);//正确,添加默认实参
局部变量不能作为默认实参。只要能转化成形参都可用。
对于默认实参求值过程发生在函数调用时。
sz wd=80;
char def=' ';
sz ht();
string screen(sxz = ht (),sz = wd ,char = def);
string window = screen();   //调用screen(ht(),80,' '),wd,def,ht的声明要出现在函数之外;
void f2()
{
    def = '*';
    sz wd= 100;
    window = screen;     //调用  screen(ht(),80,' *')
}
注意,在f2内改变了def,对scrren有影响,wd重新定义,屏蔽了外层wd,但是该局部变量与传递给screen的默认实参没有关系
内联函数
constexpr函数指的是用于常量表达式的的函数,函数的返回类型及其所有参数都得是字面值类型,而且必须有一条返回语句
constexpr函数调用时替换成其表达式的结果;,隐式的指定为内联。
constexpr函数除return外,还可以有别的语句,只要这些语句不执行任何操作,空语句,类型别名,uing声明
如果我们给constexpr函数的参数是常量表达式,返回的也是常量表达式,如果是非常量,放回的也是非常量

把内联函数和constexpr函数放在头文件中

assert ,在cassert中,#define NDEBUG  后assert不再起作用

void print(const int ia[ ],size_t size)
{
#ifndef NDEBUG
    // _ _func_ _是编辑器定义的一个局部静态变量,用于存放函数的名字,输出当前调试的函数的名字,每个函数都有
    cerr<<_ _func _ _<<":array size is "<<size<<endl;
#endif
}
_ _FILE__存放文件名的字符串的字母值。
_ _LINE_ _存放当前行号的整型字面值
_ _TIME_ _ 存放文件的编译时间的字符串字面值
_ _DATE_ _存放文件的编译日期的字符串字面值

调用重载函数时应尽量避免强制类型装换,如果确实需要,说明我们的设计形参集合不合理

为了确定最佳匹配,实参到形参转换的顺序;
    精确匹配,包括以下情况:
        实参类型和形参类型相同。
        实参从数组类型或函数类型转换成对应的指针类型。
        想实参添加顶层const或const实参中删除顶层const
    通过const转换实现的匹配
    通过类型提升实现的匹配
    通过算术类型转换或指针转型实现的匹配;
    同类类型转换实现的匹配。

给函数指针赋值,用函数名,该函数将自动转换成指针,也可以给函数名前加上&,两者等价
调用时无需提前解引用,函数可以做形参,它会自动转换成指针
typedef bool Func(const& string,const& string);                     typedef decltype(lengthcompare) Func2;
typedef bool(*Func)(const& string,const& string);                   typedef decltype(lengthcompare) *FuncP2;
使用Func2和FuncP2  一样;

必须把返回类型写成指针形式,编辑器不会自动转换
最简单的是使用别名,
using  F = int(int* , int);///F是函数类型
using PF = int(*)(int* , int)  //F是函数指针类型
PF f1(int);
F f1(int);    //错误,要使用函数指针返回
F* f1(int);
直接声明   int (*f1(int))(int* , int);
尾置返回类型
auto f1(int) -> int (*) (int*,int);

当用decltype作用于某个函数时,它返回函数类型而非指针。所以我们要显示地加上*   。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值