int i = 0;//用0.0初始化OK,但会产生截断
int i = {0};//不能用0.0初始化
int i{0};//不能用0.0初始化
int i(0);//用0.0初始化OK,但会产生截断
声明与定义
extern int i;//变量声明
extern int i = 0;//变量定义, extern不起作用
void foo(int i);//函数声明
命名规则与命名规范
C++ Primer 5ed 2.2.3 Identifies
The standard also reserves a set of names for use in the standard library. The identifiers we define in our own programs may not contain two consecutive underscores, nor can an identifier begin with an underscore followed immediately by an uppercase letter. In addition, identifiers defined outside a function may not begin with an underscore.
C++ Primer中提及到表示符中不要出现连续的两个下划线, 或者以下划线加大写字母开头, 函数外定义的变量不要以下化线开头, 但实际测试时并不会有报错信息
constint max_files =20; // max_files is a constant expressionconstint limit = max_files +1; // limit is a constant expressionint staff_size =27; // staff_size is not a constant expressionconstint sz =get_size(); // sz is not a constant expression// 因此可以使用下面的写法代替上面的写法 (基本上就是把 const 替换成 constexpr)constexprint max_files =20;constexprint limit = max_files +1;
decltype关键字
decltype(f()) sum = x;//利用f函数的返回类型得到类型
2.5 类型处理 (Dealing with Types)
2.6 自定义数据结构 (Defining Our Own Data Structures)
第 6 章: 函数 (Functions)
6.7 函数指针 (Pointer to Functions)
函数指针准确理解应该是: 指向函数类型的指针
涉及到函数指针, 类型会变得很复杂且费解, 下面的示例里主要注意这几点:
function type 与 pointer to function type 有时候会发生自动转换, 但它们是不同的东西 (C++ Primer Plus 一书中指出了这个自动转换为什么合法的原因只是两种学说有矛盾, 因此 C++ 规定自动转换是合法的)
using, decltype 在这里的使用, 通常能简化很多复杂的符号
boollengthCompare(conststring&,conststring&); // 函数的前向声明bool (*pf)(conststring&,conststring&); // 定义一个函数指针// 函数名会自动转为指针, 两种写法都一样 (猜测的解释, 函数名本身在编译时会编译为一个地址)pf = lengthCompare; // pf now points to the function named lengthComparepf =&lengthCompare; // equivalent assignment: address-of operator is optional// 同样的道理使用函数指针调用函数时解引用符号 * 也是可以省略的bool b1 =pf("hello","goodbye"); // calls lengthComparebool b2 = (*pf)("hello","goodbye"); // equivalent callbool b3 =lengthCompare("hello","goodbye"); // equivalent callpf =nullptr; // OK// 函数指针在赋值时必须函数签名完全一致, 因此函数重载时总是会匹配到唯一的一个// 将函数指针作为参数时, 下面两种写法也是没有区别的// third parameter is a function type and is automatically treated as a pointer to functionvoiduseBigger(conststring&s1,conststring&s2,boolpf(const string &,const string &));// equivalent declaration: explicitly define the parameter as a pointer to functionvoiduseBigger(conststring&s1,conststring&s2,bool (*pf)(conststring&,conststring&));// 调用以函数指针作为参数的函数// automatically converts the function lengthCompare to a pointer to functionuseBigger(s1, s2, lengthCompare);// 函数指针类型比较难写, 所以通常会用 typedef 来简化// 注意 Func 与 Func2 是等价的类型, 而 FuncP 与 FuncP2 是等价的类型// Func and Func2 have function typetypedefboolFunc(const string&,const string&);typedefdecltype(lengthCompare) Func2; // equivalent type// FuncP and FuncP2 have pointer to function typetypedefbool(*FuncP)(conststring&,conststring&);typedefdecltype(lengthCompare) *FuncP2; // equivalent type// 备注: decltype 的返回的是 function type// 然而在这里的函数时, Func 与 FuncP2 又都是等价的 (即上面 4 者都等价)// equivalent declarations of useBigger using type aliasesvoiduseBigger(conststring&,conststring&,Func); // 自动认为Func是函数指针类型voiduseBigger(conststring&,conststring&,FuncP2);// 使用 using 语法起到 typedef 的作用, 以下展示返回类型是函数指针的函数(注意一个函数的返回类型不能是函数类型, 只能是函数指针)usingF=int(int*,int); // F is a function type, not a pointerusingPF=int(*)(int*,int); // PF is a pointer type// 这里又很诡异, 返回类型必须是函数指针, 不能是函数类型PFf1(int); // ok: PF is a pointer to function; f1 returns a pointer to functionFf1(int); // error: F is a function type; f1 can’t return a functionF*f1(int); // ok: explicitly specify that the return type is a pointer to function// 表示一个返回类型是一个函数指针的函数, 这个返回的函数指针的类型是 int(int), 而这个函数的入参类型是(int*, int)int (*f1(int))(int*,int); // 很难读懂autof1(int) -> int (*)(int*,int); // 与上面等价, 但很难读懂string::size_typesumLength(conststring&,conststring&); // 函数声明string::size_typelargerLength(conststring&,conststring&);// depending on the value of its string parameter,// getFcn returns a pointer to sumLength or to largerLengthdecltype(sumLength) *getFcn(const string &);// genFcn 是一个函数指针, 函数的返回值是一个 sumLength 函数指针, 函数的入参是(const string&)