1 当用实参初始化形参时会忽略掉顶层const。形参顶层const被忽略掉了,当形参有顶层const时,传给它常量对象或者非常量对象都是可以的。
void fcn(const int i){}
void fcn(int i )//错误:重复定义了fcn(int)
因为顶层const被忽略掉了,所以在上面的代码中传入两个fcn函数的参数可以完全一样。
2 尽量使用常量引用,因为若定义为常量引用,则说明 1 这个参数不能被改变,2 可以赋予常量引用以字面型常量(如int string类型常量),普通的引用形参的局限性在于不能把const对象,字面值或者需要类型转换的对象。
3 数组有两个特殊的性质,
1) 不允许拷贝数组。 如 int a[10] = {0};int b [] = a; b = a; //后两种行为都是非法的。
2)使用数组时会将其转换成指针。
4 数组引用形参
//形参是数组的引用,维度是类型的一部分
void print(int (&arr)[10])
{
for(auto elem:arr)
cout<<elem<<endl;
}
注意的是数组引用的形式
int &arr[10];//错误:数组中需要为一个对象,引用非对象
int (&arr)[10];//arr是具有10个整数的整型数组的引用
int (*arr)[10]; //arr为指向数组的指针
int *arr[10]; //arr为指针数组
5 传递多维数组
当将多维数组传递给函数时,真正传递的是指向数组首元素的指针。首先元素本身就是一个数组,指针就是一个指向数组的指针。数组的第二维(以及后面所有维度)的大小都是数组类型的一部分,不能忽略。
void print(int (*matrix)[10],int rowsize){/*...*/}
void print(int matrix[][10], int rowsize){/*...*/}
6 含有可变形参的函数
原因:程序无法提前预知应该向函数传几个实参数。
1 C++11新标准标准提供了两种主要的方法:
1)如果所有实参类型相同,可以传递一个名为initializer_list的标准库;
2)如果实参的了性不同,我们可以编写一种特殊的函数,也叫做可变参数模版;
initializer_list 是一种标准库类型,用于表示某种特定类型的值得数组。与vector类似,有类似的操作但是不同点在于initializer_list中的元素是不可修改的,为常量值。
initializer_list<T> lstl;默认初始化:T类型元素的空列表。
initializer_list<T> lst{1,b,c...};lst的元素数量和初始值一样多;lst的元素是对应初始值的副本;列表中的元素是const;
lst2(lst); //拷贝或复制一个initializer_list对象不会拷贝列表中的元素;
lst2 = lst; //拷贝后,原始列表和副本共享元素
lst.size(); //列表中的元素数量
lst.begin(); //返回指向lst中首元素的指针
lst.end(); //返回指向lst中尾元素下一位置的指针
2 省略符形参是为了便于C++程序访问某些特殊的C代码而设置的,应该仅仅用于C和C++通用的类型。
void foo(param_list,...)
void foo(...)
7 列表初始化返回值
C++11新标准规定,函数可以返回花括号包围的值得列表。此处列表也用来对表示函数的临时量进行初始化。因此返回值得类型需要可以被列表初始化。
8 返回数组指针
数组不可以被拷贝,因此函数不能返回数组。想要定义一个返回数组的指针或引用的函数。
1) 使用类型别名。
typedef int arrT[10];
using arrT = int[10];
arrT* func(int i)//func返回一个指向含有10个整数的指针
2) 声明一个返回数组指针的函数。
形式如:
Type (*function(parameter_list))[dimension]
3) 使用尾置返回类型
c++11新标准中还有一种可以简化上述func声明的方法,就是尾置返回类型(trailing return type)。
//返回一个指针,指向含有10个整数的数组
auto func(int i) -> int(*)[10];
4) 使用decltype返回数组类型
int odd[] = {1,3,5,7,9};
int even[] = {0,2,4,6,8};
decltype(odd) *arrPtr(int i)
{
return (i&2) ? &odd:&even;
}
9 inline内联函数,内联说明只是向编译器发出一个请求,编译器可以选择忽略这个请求。
一般来说,内联机制用于优化规模较小,流程直接,频繁调用的函数。
10 constexpr函数是指用于常量表达式的函数。
函数的返回值类型以及所有形参的类型都得是常量(需要在编译器确定),(若为非字面值类型,则为非常量表达式),而且函数体中必须有且只有一条return语句。
11 对于某个给定的内联函数或者constexpr函数来说,它的多个定义必须完全一致。基于这个原因,内联函数和constexpr函数通常定义在头文件中。
12 const_cast和重载
const_cast在重载函数的情景中最有用,当一个函数它的形参是一个常量,但是实参不是一个常量,可以通过const_cast转换来实现。
const string &shortString(const string &s1,const string &s2)
{
return s1.size()<s2.size() ? s1:s2;
}
string &shortString(string &s1, string &s2)
{
auto &r = shorterString(const_cast<const string&>(s1),const_cast<const string&>(s2));
return const_cast<string&>(r);
}
13 assert()在cassert文件中
NDEBUG 预处理变量,可以在文件中设置,也可以在编译选项中设置-D NDEBUG
--FILE--
--LINE--
--TIME--
--DATE--
14 返回指向函数的指针应当注意的是当我们将decltype作用于某个函数时,它返回函数类型而非指针类型,因此我们需要显式的加上*以表示需要返回指针类型。
/*--------1---------*/
using F = int(int*,int);
using PF = int(*)(int*,int);
PF f1(int);//PF是指向函数的指针,f1返回指向函数的指针
P *F1(INT);
/*--------2---------*/
int (*f1(int))(int*,int);
/*--------3---------*/
auto f1(int) -> int (*)(int*,int);
/*--------4---------*/
string::size_type sumLength(const string&,const string&);
string::size_type largerLength(const string&,const string&);
decltype(sumLength) *getFcn(const string &);
--------------------------------------------------------
6.3.3节练习
string(&func(para))[10];
typedef string arrT[10];
using arrT = string[10];
arrT& func(para);
//decltype(arrS) 返回的是数组类型,因此需要加一个&
string arrS[10];
decltype(arrS) &func(para);
auto func()->string(&)[10];