目录
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;
}
<>指出类型, 并在声明开头添加关键字templatetemplate 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