细则:auto不能用于以下四种情况:1)函数形参。2)非静态成员,包括有初始化的。3)auto数组。4)模板参数,如 vector<auto>
-
static_assert(常量表达式,“some tips”); 用于库作者,判断条件必须是常量表达式。
-
成员变量初始化。用=号或者{},不过优先级低于初始化列表。而且只作用于非静态成员。
#include <iostream> class Mem{ public: Mem(int i):m(i){} private: int m=0; char a{'g'}; static mystr="123"; //这个是不行的,要到类外初始化 };
-
sizeof在原有基础上,新增可用于类未实例化对象时,获取其类成员大小。
意思是sizeof(A::avalue),相当于以前的,sizeof(((A*)0)->avalue)。
-
final,继承中,当前类重写了父类virtual函数,而且不想被此类的派生类再重写。(类似java的final)
void fun() final;
override为了跨类继承和代码可阅读性,还有可以通过编译器提示发现如下错误,不写的话只能自己查代码,没有编译器信息提示。
struct Base{ virtual void Turing() = 0; virtual void Dijkstra() = 0; virtual void VNeumann(int g) = 0; virtual void DKnuth() const; void Print(); } struct DerviedMid:public Base{ //void VNeumann(double g); //接口被隔离,曾想重载 }; struct DerviedTop:public DerivedMid{ void Turing() override; void Dikjstra() override; //无法编译通过,函数名拼写错误 void VNeumann(double g) override; //无法编译通过,参数不一致,并非重载 void DKnuth() override; //无法编译通过,常量性不一致 void Print() override; //无法编译通过,非虚函数重载 };
-
外部模板,减少链接器开销,举例:
test.h: template<typename T>void fun(T){} test1.cpp: #include<test.h> template void fun<int>(int); void test1(){fun(3);} test2.cpp: #include<test.h> extend template void fun<int>(int); //外部模板声明 void test2(){fun(4);} //链接文件---- test1.o fun<int>(int) test2.o null //链接成一文件: fun<int>(int)
-
POD五个原则:1)所有非静态成员有相同的访问权限(public,private,protected)。2)在类或者结构体继承时,满足以下两种情况之一:●派生类中有非静态成员,且只有一个仅包含静态成员的基类。●基类有非静态成员,而派生类没有非静态成员。3)类中第一个非静态成员的类型与其基类不同。4)没有虚函数和虚基类。5)所有非静态数据成员均符合标准布局类型,其基类也符合标准布局。这是一个递归的定义,没有什么好特别解释的。
-
>>这个会自动判别是右移运算符还是界定符了。如static_cast<vector<int>>
-
auto必须有初始化值。优势在于拥有初始化表达式的复杂类型变量声明时简化代码。如用于STL迭代器类型,auto==vector<int>::iterator。auto
-
decltype,用于模板,和auto结合,泛型编程。取类型,如decltype(v.begin)就是iterator咯。追踪返回类型:
template<typename T1,typename T2> auto Sum(T1 & t1,T2 & t2) -> decltype(t1+t2){ return t1+t2; }
-
for循环。for(auto e:arr);不能用于未确定范围,例如int func(int a[]){for(auto e:a){}} 会有问题。因为a[]未确定。