1、函数声明负责指定函数的名字、返回值(如果有的话)的类型以及调用该函数所需的参数数量和类型。
2、函数声明包含多种限定及修饰符,如下:
- 函数的名字,必选。
- 参数列表,可以为空(),必选。
- 返回类型,可以是void,可以是前置或者后置形式(使用auto),必选。
- inline,表示内联函数体实现函数调用。
- constexpr,表示当给定常量表达式作为实参时,应该可以在编译时对函数求值。
- noexcept,表示该函数不允许抛出异常。
- 链接说明,例如static。
- [[noreturn]],表示该函数不会用常规的调用/返回机制返回结果。
- virtual,表示该函数可以被派生类覆盖。
- override,表示该函数必须覆盖基类中的一个虚函数。
- final,表示该函数不能被派生类覆盖。
- static,表示该函数不与某一特定的对象关联。
- const,表示该函数不能修改其对象的内容。
3、在C和C++中,返回类型位于声明语句一开始的地方。然而,我们也可以在函数声明中把返回类型写在参数列表之后。
string to_string(int a); //前置返回类型
auto to_string(int a) -> string; //后置返回类型
4、inline限定符告诉编译器,应该尝试调用生成内联代码。
5、当constexpr出现在函数定义中时,它的含义是“如果给定了常量表达式作为实参,则该函数应该能用在常量表达式中”。而当constexpr出现在对象定义中时,它的含义是“在编译时对初始化器求值”。
6、函数必须足够简单,才能在编译时求值:constexpr函数必须包含一条独立的return语句,没有循环,也没有局部变量。同时,constexpr函数不能有副作用。
7、形如[[...]]的概念被称为属性。通常情况下,属性描述了位于它前面的语法实体的性质。C++只包含两个标准属性:[[noreturn]]、[[carries_dependency]]。把[[noretrun]]放在函数开始的位置,表示我们不希望该函数返回任何结果。
8、函数内部的名字称为局部名字。每次调用函数时都会拥有该变量的一份拷贝。相反,如果我们将局部变量声明成static,则在函数的所有调用中都将使用唯一的一份静态分配的对象,该对象在线程第一次到达它的定义处时被初始化。
9、如何选择参数的传递方式呢,我的经验准则是:
- 对于小的对象使用值传递的方式。
- 对于你无需修改的大对象使用const引用传递。
- 如果需要返回计算结果,最好使用return而非通过参数修改对象。
- 使用右值引用实现移动和转发。
- 如果找不到合适的对象,则传递指针。
- 除非万不得已,否则不要使用引用传递。
10、一个由{}限定的列表可以作为下述形参的实参:
- 类型std::initializer_list<T>,其中列表的值能隐式地转换成T
- 能用列表中的值初始化的类型
- T类型数组的引用,其中列表的值能隐式地转换成T
11、当某些函数,很难明确指定调用时期望的参数数量和类型。有三种选择:
- 使用可变模板
- 使用initializer_list
- 使用省略号(...)结束参数列表,表示“可能有更多的参数”
12、如果用户提供的参数数量不足,则使用预置的默认参数。
complex(double r ={}, double i ={}) :re{r} : im{i} {}
13、为不同数据类型的同一种操作起相同的名字称为重载。在重载解析过程中,不考虑函数的返回类型,这样可以确保对运算符或者函数调用的解析独立于上下文。
14、指向函数的指针被称为函数指针,程序员只能对函数做出两种操作:调用它或者获取它的地址。解引用函数指针时,可以用*,也可以不用。同样,获取函数地址时,可以用&,也可以不用。
15、使用类型转换reinterpret_cast来执行函数指针的转换。
16、函数指针必须反映函数的链接信息。链接说明和noexcept都不能出现在类型别名中。
17、编译器预定义了一些宏:
- __cplusplus:C++编译器中有定义,在C++11程序中它的值是201103L。
- __DATE__:“yyyy:mm:dd”格式的日期。
- __TIME__:“hh:mm:ss”格式的时间。
- __FILE__:当前源文件的名字。
- __LINE__:当前源文件的代码行数。
- __FUNC__:是一个由具体实现定义的C风格字符串,表示当前函数名字。
- __STDC_HOSTED__:如果当前实现是宿主式的则为1,否则为0。
- __STDC__:在C语言编辑器中有定义。
- __STDC_MB_MIGHT_NEQ_WC__:在wchar_t编码体系中,如果基本字符集的成员值与它作为普通字符字面值常量的值可能不同,则为1。
- __STDCPP_STRICT_POINTER_SAFETY__:如果当前实现有严格的指针安全机制,则为1;否则未定义。
- __STDCPP_THREADS__:如果程序可以有多个执行线程,则为1;否则是未定义的。
18、#progma foo bar 666 foobar 如此为预处理编译指令。(避免使用)