重学C++Primer笔记5---一些基本语法需要特别注意的地方


  对于熟练C或者C++的人来说,熟读和熟记并理解下面的内容是有很大的帮助的,这涉及到了整本C++ Primer,要在实践中好好去体会和实现下面的要点。以此作为笔记,不厌其烦的去理解,好好学习。

  • 内置类型的存储空间依机器而定,但规定了每个算术类型的最小存储空间
  • 字符串字面值区分宽字符串是以宽空字符结束的
  • 使用了未定义行为的程序都是错误的,即时程序能够运行,也只是巧合。(提示:反斜杠)
  • 变量的初始化形式包括:复制初始化(等号)和直接初始化(括号),对类类型的对象来说,有些初始化仅能用直接初始化完成。
  • 初始化、赋值、定义要理解
  • 内置类型变量是否自动初始化取决于变量定义的位置
  • 类类型变量的初始化:如果定义某个类的变量时没有提供初始化式,这个类也可以定义初始化时的操作。它是通过定义一个特殊的构造函数即默认构造函数来实现的;
  • 有些类类型没有默认构造函数,那就必须提供显示的初始化式
  • 在一个程序中,变量有且仅有一个定义
  • 定义也是声明
  • extern 声明不是定义,也不分配空间;只有当声明也是定义时,声明才可以初始化式,如果声明有初始化式,那么它可被当作是定义,基石声明标记为extern,不过只有当extern 声明位于航速外部时,才可以含有初始化式;
  • C++中,大多数作用域是通过用花括号来界定的
  • 全局作用域、局部作用域、语句作用域、类作用域、命名空间作用域
  • 通常把一个对象定义在它首次使用的地方是一个很好的办法
  • const 对象:常量在定义后就不能被修改,所以定义时必须初始化
  • 与其他变量不同,除非特别说明,在全局作用域声明的const 变量是定义该对象的文件的局部变量。此变量只存在被定义的那个文件中,不能被其他的文件访问
  • 但是通过指定const变量为extern,就可以在整个程序中访问const对象(非const对象默认为extern)
  • 引用是一种复合类型,通过在变量名前添加“&”符号来定义。
  • 引用只能绑定一次对象;引用不能为数组;
  • const 引用是指向const对象的引用;const 引用可以绑定到不同但相关类型的对象或绑定到右值(原因:中间变量);
  • 非const引用只能绑定到与该引用同类型的对象;
  • 枚举成员值可以不是唯一的,即可以有同样的值
  • 不能改变枚举成员的值,枚举成员本身就是一个常量表达式,因此也可以用于需要常量表达式的地方
  • 枚举类型的对象的初始化或赋值,只能通过其枚举成员或同一枚举类型的其他对象来进行,如枚举变量Week week = Mon;
  • 定义变量和定义数据成员存在非常重要的区别:一般不能把类成员的初始化作为其定义的一部分。当定义数据成员时,只能指定该数据成员的名字和类型。类不是在类定义里定义数据成员时初始化数据成员,而是通过称为构造函数的特殊成员函数控制初始化。
  • 用class和struct关键字定义类的唯一差别在于默认访问级别:默认情况下,struct的成员为public,而class的成员为private
  • 编译器把目标文件链接在一起形成可执行文件
  • 头文件包含在多个源文件中,所以不应该含有变量或函数定义,区别类中的数据成员的定义
  • 当在头文件中定义const变量后,每个包含该头文件的源文件都有了自己的const变量,其名称和值都一样,相当与没包含一次就定义了同名同值的const变量,且const变量如果不加显示的extern,只能在本文件中使用,所以不会发生重定义错误,不同于普通变量,但是加了extern的话如果多次包含就是出现重定义的错误
  • 避免多重包含:预处理变量。使用预处理变量可以防止多次包含同一个头文件。机制就是重包含了,通过预处理变量只对#ifndef后面的内容处理一次
  • 不可能定义一个void类型的变量,最经常用作不返回结果的函数的返回类型;当区别特殊指针类型void*,它可以保存任何类型对象的地址,但是不允许使用void*指针操纵它指向的对象;
  • 区别字符串字面值和标准库string类型不是同一种类型。当进行string对象和字符串字面值混合连接操作时,+操作符的左右操作数必须至少有一个是string类型。如string ss = “world”;string str = “hello” + “, ” + ss;这是错误的操作。
  • 现在C++程序中尽量使用vector和迭代器类型,而避免使用低级的数组和指针。设计良好的程序只有在强调速度时才在类实现的内部使用数组和指针
  • 指针是数组的迭代器
  • 指向const对象的指针(地址可以变,值不可变);const指针(地址不可变,值可以变);指向const对象的const指针(地址和值均不可变);
  • C风格字符串既不能确切地归结为C语言的类型,也不能归结为C++语言的类型,而是以空字符null(\0或0)结束的字符串数组;如char str[]={‘C’,’+’,’+’};不是以null结尾的字符串,容易出问题;
  • 对于动态分配的数组,其元素只能初始化为元素类型的默认值,而不能像数组变量那样,用初始化类表初始化为指定的初值;
  • 可以用C风格字符串初始化string类型变量,但是不能用string对象初始化字符指针,可以通过c_str()函数来实现string到char *的初始化;
  • 数组、指针和引用都是复合类型;
    -如果两个操作数都是负数,除法操作的结果为正数(或零),而求模操作的结果则是负数(或零);如果只有一个操作数为负数,这两种操作的结果取决于机器;
  • 对于操作符优先级:单目操作符>双目操作符;算术运算符>位移操作符>关系运算符>逻辑运算符>条件运算符>复合运算符
  • C++保证:delete 0值的指针是安全的;一旦删除了指针所指向的对象,立即将指针置为0,这样就非常清楚的表明指针不再指向任何对象;
  • 指向任意数据类型的指针都可以转换为void *类型;整数值常量0可转换为任意指针类型;
  • 程序员避免使用强制类型转换,不依赖强制类型转化也能写出很好的C++程序;
  • 预处理器:#undef,取消定义的宏;#if,如果条件为真,则编译下面的代码;#ifdef,如果宏已经定义,则编译下面的代码;#ifndef,如果宏没有定义,则编译下面的代码;#define ;#include;
  • 实参与形参:实参的类型必须与对应的形参的类型完全匹配,即实参具有与形参类型相同、或者能够隐式转换为形参类型的数据类型;
  • 函数不能返回另一个函数或者内置数组类型,但可以返回指向函数的指针,或指向数组元素的指针的指针;
  • 在定义和声明函数时,没有显式指定返回类型是不合法的,但在早期C++版本可以接受没有返回类型的函数定义和声明,编译时会将函数类型隐式的定义为int型,但在标准C++中,这样做是错误的;
  • 引用形参:应该将不需要修改的引用形参定义为const引用;
  • 数组形参:void print(int ){}与void print(int []){}与void print(int [10]),则三种定义是等价的,形参类型都是int 型;跟形参的数组长度也无关,编译器也不会去检查数组的长度;
  • 引用形参传递数组:void print(int (&arr)[10]){},这时编译器会检查数组实参的大小与形参大小是否匹配,也不会将数组实参转化为指针,而是传递数组的引用本身;
  • 多维数组传递:数组指针,int (matrix)[10],即列宽为10,类型为int的矩阵;区别指针数组,int *matrix[10],即10个int 的数组;
  • 可变形参的函数:…;可通过#include 头文件来处理;
  • 千万不要返回局部对象的引用:当函数执行完毕后,将释放分配给局部对象的存储空间,此时,对局部对象的引用就会指向不确定的内存。
  • 千万不要返回指向局部对象的指针:和返回局部对象的引用一样的道理;
  • 静态全局变量或函数只能在定义的源文件中使用,不同于全局变量,加extern可变为多文件使用;
  • 指定默认实参的约束:既可以在函数声明也可以在函数定义中指定默认实参,但是,在一个文件中,只能为一个形参指定默认实参一次。在两个文件中,默认实参在声明中指定,不过一般也在声明中指定默认实参;
  • 一般来说,内联机制适用于优化小的、只有几行的而且经常被调用的函数。大多数编译器都不支持递归函数的内联。内联函数应该在头文件中定义,这一点不同于其他的函数;在头文件中加入或者修改内联函数时,使用了改头文件的所有源文件都必须重新编译;
  • 编译器隐式地将在类内定义的成员函数当作内联函数;
  • const 对象、指向const对象的指针或引用只能用于调用其const成员函数,如果尝试用它们来调用非const成员函数,则是错误的。
  • 构造函数是特殊的成员函数,与其他成员函数不同,构造函数和类同名,且没有返回类型;
  • 构造函数应确保每个数据成员都完成了初始化;
  • 构造函数的初始化列表:在冒号和花括号之间的代码成为构造函数的初始化列表;如ClassName() : val(0),val1(0) {}
  • 合成默认构造函数:如果没有为一个类显式定义任何构造函数,编译器将自动为这个类生成默认的构造函数;
  • 对于重载函数:形参名只是帮助文档,并没有修改形参表;
  • 形参与const形参的等价性仅适用于非引用形参,仅当形参是引用或指针时,形参是否为const才有影响;
  • 在函数中局部声明的名字(无论是变量名还是函数名)将屏蔽在全局作用域内声明的同名名字;
  • 重载:f(int *)与f(int *const)不是重载,此时,const用于修饰指针本身,而不是修饰指针所指向的类型。
  • 在引用函数名但没有调用该函数时,函数名将会自动解释为指向函数的指针。
  • 直接引用函数名等效于在函数名上应用取地址操作符;
  • 指向函数的指针可用于调用它所指向的函数,可以不需要使用解引用操作符,直接通过指针调用函数;
  • 允许将形参定义为函数类型,但函数的返回类型则必须是指向函数的指针,而不能是函数;
智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告