C++高阶之你不知道的冷知识

  1. 函数模板的返回值不确定时候,可以参考一下C++11新增的后置声明停下进行声明: templat<class T1,class T2>  auto gt(T1 x,T2 y)->decltype(x+y){ return x+y;}
  2. 定义在类声明中的函数自动成为内联函数。如果要显式将成员函数变成内联函数,只需要在函数定义前加上inline关键字即可
  3. 只有一个参数的构造函数允许使用赋值语法对其进行初始化,若要禁止其隐式转换,可以使用explicit关键字进行修饰
  4. 初始化对象数组的方案是:首先使用默认构造函数创建数组元素,然后花括号中的构造函数将创建临时对象,然后最后将临时对象复制到响应的元素内,因此如果要创建类对象数组,则这个类必须有默认构造函数。
  5. C++11提供了一个新枚举,其枚举量的作用域为类:enum class :short egg{Small,Media,Large};
  6. 可将派生类对象直接赋值给基类,但内容只涉及基类部分
  7. 在菱形继承时,禁止信息通过父类传递给祖父类,所以在构造子类时,其父类不会调用祖父类的构造函数,而只会调用其默认构造函数。若要调用祖父类的带参构造函数,需要在子类声明时,带上祖父类的带参构造函数。
  8. 任何小于int类型的两个正数相加,在相加之前都会将其提升为int类型后,再进行操作。----整型提升
  9. 两个文件内分别有全局变量和静态变量,在全局变量的文件中使用静态变量时候,因为无法确认此时静态变量是否以及初始化完成,结果也不确定
  10. C++只允许一层指针的const自动类型转换
  11. new失败不会返回空指针,只会抛出异常,唯一可以使其返回空指针的方法是在new后面加上(std::nothrow),例如 int* p = new (std::nothrow) int;
  12. STL的array在栈上分配内存,vector在堆上分配,pair无内存管理,在哪里申请在哪里分配
  13. STL的remove_if算法不会删除元素,只是把待删除的元素移动到末尾
  14. STL算法中的remove_copy_if在使用前需要为容器申请元素
  15. noexcept只是告诉编译器这个函数不会抛出异常,对其不做异常方面的处理,从而提升效率,但是实际是否抛出异常,由开发者自己决定,如果声明了noexcept,结果却抛出了异常,编译器将对其不做处理,程序将直接退出
  16. 如果一个类的移动构造函数使用了noexcept,则在对包含这个类的容器进行扩张时候,将使用移动拷贝,否则将使用复制拷贝,注意只有在扩展的时候才会体现出差别来
  17. const类型的引用变量只能在类的初始化列表内进行初始化
  18. static成员变量只能在类外进行初始化,但static const的类型的成员变量可以在类内进行初始化
  19. 不可以对成员函数同时使用static及const(前缀修饰)进行修饰,因为C++编译器在实现const函数时,为了确保该函数不会修改对象的成员,会传入一个隐式的参数:const this *,但static函数是没有this指针的,也就是说static与const是冲突的。
  20. 当不希望某个类被继承或者某个虚函数被重写,可以在类名或虚函数名后添加一个final关键字进行修饰,表示其不可被重写,如果被误重写,编译时,编译器会报错
  21. 初始化顺序:(1)基类的静态变量 (2)派生类的静态变量 (3)基类的成员变量  (4)父类构造函数(5)派生类的成员变量(6)派生类构造函数
  22. C++中*与&同时修饰形参时是什么意思,例如int insert(int *& head):本来传入*head,便是形参head是指针,只能改变其所指向的内容,但是通过&修饰后,表示指针head的指向也可以被修改。
  23. 哪些函数不能成为虚函数:(1)全局普通函数 (2)友元函数 (3)构造函数 (4)内联成员函数 (5)静态成员函数
  24. 不可以在一个类内声明两个同名同参的虚成员函数及静态成员函数,编译器分不清
  25. 虚函数不可以是内联的,因为内联函数是在编译时决定的,但是虚函数时运行时决定的,即使在虚函数前加上inline关键字,但仍然会被忽略
  26. 函数加上const修饰和不加const修饰,其实是两个函数,所以在父类中某虚函数加上const,但是同名同参的子类成员函数没有加上const,不会被重写
  27. STL中const_iterator指的是迭代器的指向的内容不可以修改,但是迭代器可以进行++操作
  28. 不能将一个数组直接赋值给另一个数组,字符串数组也不行,但可以将一个结构直接赋值给另一个结构
  29. 数组可以使用大括号形式进行初始化且可以省略等号,但这个只能在初始化时候使用,例如 int[12]{0};表示将第一个元素初始化为0,其余元素使用默认值,即也为0
  30. cin.getline(str,size)与cin.get(str,size)都表示读取整行字符串直到读取到了换行符或size个字节,但cin.getline(str,size)在读取到换行符时候,将其取走并使用’\n’代替换行符,而cin.get(str,size)则会将换行符留在队列中,此时可以使用它的变体cin.get()读取这个字节。注意输入参数指令:cin>>str;也会将换行符留在队列中
  31. 字符串的前缀u、U、L、R分别代表char16_t、char32_t、wchar_t以及原始字符串
  32. C++要求枚举变量只能用枚举值进行赋值
  33. 对一个空指针进行delete或free操作将什么也不做
  34. 数组名是指针常量,是数组首元素的地址,对数组名取地址就是整个数组
  35. 前缀自加加比后缀自加加效率要高,因为前缀直接返回其值加1的结果,而后缀则会先复制一个副本,然后让副本加1,再返回副本。当然C++内置类型(int、double)没有区别
  36. cin将忽略换行符和空格符,此时可以使用cin.get()将其读取
  37. 字符函数库为cctype
  38. 使用引用作为形参时,其实参类型必须与形参引用的类型一致,例如func(int& i),此时如果传入long类型的变量将会报错,且传的必须为左值,除非该形参加上了const修饰。
  39. 如果函数使用const引用作为形参,而调用函数时,传入的是常量或与形参const引用类型不匹配,C++将创建临时匿名变量存储该值
  40. 函数使用引用作为形参时,尽量使用const修饰,好处如下:(1)可以避免无意中修改数据的编译错误(2)使用const引用可以使函数接受const和非const实参,否则只能接受非const (3)使用const引用使函数可以正确生成并使用临时变量
  41. 类型引用和类型本身视为同一特征标。const是否可以作为函数重载特征标视情况而定   https://www.cnblogs.com/qingergege/p/7609533.html
  42. 函数模板:显示具体化:template<>void Swap<Job>(Job& j1,Job& j2);显示实例化:template void  Swap<Job>(Job& j1,Job& j2); 注意:显示实例化不包含 <>,可以通过函数使用创建显示实例化:Swap<Job>(j1,j2);
  43. 函数重载的调用顺序:(1)创建候选函数列表,即函数名称相同的所有函数,包括函数模板 (2)筛选出参数个数匹配的函数,包括默认参数(3)匹配最佳:完全匹配,a、常规函数优于模板 b、提升转换,即int->long  c、用户自定义转换
  44. 在函数模板中如果不知道变量类型,可以使用decltype修饰,其将根据实际传入的参数类型生成准确的类型,例如:decltype(expression) var; 具体判断逻辑如下:(1)如果expression没有使用括号括起来,则类型与expression完全相同,例如 const int i =0; decltype(i) var;则var为const int.(2)如果expression是一个函数调用,则var与函数返回值相同。注意,此时并不会调用函数,编译器通过函数原型,获取返回类型(3)如果expression是一个左值且使用括号括起来,则var为其类型的引用。例如int i =0; decltype((i)) var;则var为int&,(4)以上情况都不满足,则var与expression完全相同.例如 long i =0;decltype(i+6)var;此时var为long类型。

猜你喜欢

转载自blog.csdn.net/Chiang2018/article/details/113829577