目录
C++内联函数其实是对C中的宏的优化(或者说新的实现方法)。使用内联函数代替宏能避免某些错误的风险。
至少在函数声明与函数定义之中的一处使用关键字inline
,可以使函数成为内联函数。在类声明中定义的函数会被自动转换为内联函数。
内联函数的调用语句会被编译器自动替换为函数的代码。从而省去了调用函数所需的时间。
通过创建拥有不同参数列表的同名函数,可以实现函数重载。重载函数的返回值可以不同,但不能作为区分不同重载函数的标准,也就是说不能用来进行函数重载。
第三代具体化(IOS/ANSI C++标准)
- 对于给定的函数名,可以有非模版函数、模板函数、和显式具体化模板函数及它们的重载版本。
- 显式具体化的原型与定义应以
template<>
打头,并来指出类型。- 具体化模板优先于常规模板,而非模板函数优先于模板函数。
隐式实例化、显式实例化、显式具体化统称为具体化
模版函数定义(typename
可以用 class
代替):
template<typename AnyType>
bool isgreater(AnyType a, AnyType b)
{
if(a > b)
return true;
return false;
}
decltype
的作用是检测表达式的类型(type),并将其用来指出类型。常常在模板函数中使用。
decltype(expression) var;
decltype
还可以搭配auto
实现的后置类型声明处理特殊的函数返回值。常常用于模板函数。
后置类型声明
auto h(int x, float y) -> double;
搭配decltype
,用于模板函数
template<typename T1, typename T1>
auto h(T1 x, T2 y) -> decltype(x + y)
{
// ...
return x + y;
}
假设定义了一个类Data
, Data
中有成员number
// 原型
template<> isgreater<Data>(Data, Data); // <Data>是可选的
// 定义
template<> isgreater<Data>(Data a, Data a) // <Data>是可选的
{
if(a.number > b.number)
return true;
return false;
}
<>
指出类型, 并在声明开头添加关键字template
template isgreater<int>(int, int);
!注意: 在同一文件(或转换单元)中若已有显式具体化, 编译器不会隐式创建实例, 使用同一类型的显式具体化和显式实例化将会导致错误
可行函数从最佳到最差的顺序:
char
和short
自动转换为int
, float
自动转换为double
, double
自动转换为Long double
)int
转换为char
, long
转换为double
)识别完全匹配时, C++允许进行"无关紧要的匹配", 如下(Type指其他类型而非变量名):
从实参 | 到形参 | 注 |
---|---|---|
Type | Type & | |
Type& | Type | |
Type [] | Type* | 数组到指针 |
Type(argument-list) | Type (*)(argument-list) | 函数名到函数指针 |
Type | const Type | |
Type | volatile Type | |
Type* | const Type* | |
Type* | volatile Type* |
const
数据的指针或引用优先于指向const
数据的指针或引用对于第一条, 需注意模板函数与非模板函数的不同, 参考以下代码:
1. 对非模板函数, 见上文
#include <iostream>
using namespace std;
void func(int &){
cout << "int &" << endl;
}
void func(const int &){
cout << "const int &" << endl;
}
int main()
{
int i;
int& ri = i;
func(ri);
return 0;
}
输出:
int &
2. 对模板函数, 见下文"部分排序规则"
#include <iostream>
using namespace std;
template<typename T>
void func(T &){
cout << "T &" << endl;
}
template<typename T>
void func(const T &){
cout << "const T &" << endl;
}
int main()
{
int i;
int& ri = i;
func(ri);
return 0;
}
输出:
const T &
有多个与函数调用的自变量列表匹配的函数模板可用。 C++ 定义了函数模板的部分排序以指定应调用的函数。 由于有一些模板可能会视为专用化程度相同,因此排序只是部分的。
编译器从可能的匹配项中选择可用的专用化程度最高的模板函数。 例如, 如果一个函数模板采用类型T
, 而另一个所采用T*
的函数模板可用, 则T*
认为该版本更为专用化。 只要参数是指针类型, 就优先使用T*
泛型版本, 即使两者都是允许的匹配项。
通过以下过程可确定一个函数模板候选项是否更加专用化(more specialized):
T*
采用一个模板的专用化比只T
采用一个模板更为专用, 因为X*
假设类型是T
模板参数的有效参数, 但X
它不是有效的参数T*
模板参数。const T
比T
更专业化, 因为const X
是模板参数T
的有效参数, 但const T
不是模板参数X
的有效参数。const T*
比T*
更专业化, 因为const X*
是模板参数T*
的有效参数, 但const T*
不是模板参数X*
的有效参数。简单地说, 哪一个模板指出的细节更多就使用哪个
示例
// partial_ordering_of_function_templates.cpp
// compile with: /EHsc
#include <iostream>
template <class T> void f(T) {
printf_s("Less specialized function called\n");
}
template <class T> void f(T*) {
printf_s("More specialized function called\n");
}
template <class T> void f(const T*) {
printf_s("Even more specialized function for const T*\n");
}
int main() {
int i =0;
const int j = 0;
int *pi = &i;
const int *cpi = &j;
f(i); // Calls less specialized function.
f(pi); // Calls more specialized function.
f(cpi); // Calls even more specialized function.
// Without partial ordering, these calls would be ambiguous.
}
输出
Less specialized function called
More specialized function called
Even more specialized function for const T*
在函数声明中可以指定参数的默认值。
第一个默认参数后只有默认参数。
在函数头与函数声明中, int arr[]
与int* arr
等效
仅当引用形参为const
时, 编译器才会在实参与形参不匹配时生成临时变量。
C中一开始将等式左边的实体称为左值, 但在引入
const
关键字后情况发生了变化。现在的情况是将可以被引用的数据对象称为引用, 是否为const
对是否为左值并没有影响。
- 左值: 变量、数组元素、结构成员、引用、解除引用的指针(如
*p
,p
为指针)- 非左值: 字面常量(C-style 字符串除外, 其值类似指针常量)、包含多项的表达式
若形参为普通引用, C++中一般禁止创建临时变量。
因为使用普通引用一般是为了修改实参的值, 若允许产生临时变量, 可能会产生不易察觉的错误。
原文:https://www.cnblogs.com/alohana/p/12293157.html