ch2
2.1 基本内置类型
C++基本内置类型
-
void
-
算术类型
-
整形(包括字符,bool)
-
浮点型
-
最小尺寸:
-
整形尺寸大小受编译器影响,但是至少会保证一个最小尺寸,int最小尺寸2字节
-
相互关系:int至少和一个short一样大
无符号类型:unsigned int、unsigned long
类型转换规则:
-
布尔<->非布尔
-
整形<->浮点型
-
unsigned超过最大表示范围:对无符号表示范围取模后的余数
-
带符号超过最大表示范围:未定义
对无符号的计算应谨慎:
算术表达式兼有signed 、unsigned,将结果转成unsigned
unsigned u = 10, u2 = 42;
std::cout << u2 - u << std::endl; //32
std::cout << u - u2 << std::endl; //4294967264超过无符号表示范围,取余
字面值:
-
不同进制的整形字面量
-
浮点字面量的指数(1E3)
-
字符串""、字符''、转义字符、泛化转义序列(\x+16进制数字 or +8进制数字)
-
布尔、指针字面量
字面值类型:没找到准确定义,,姑且看作是可以用字面值体现的类型,包括算术类型、指针、引用+一部分满足要求的类(字面值常量类,7.5介绍)。string不是字面值类型。
2.2 变量
变量初始化定义:创建时获得一个特定值
初始化方式:
-
默认初始化(创建时未被指定类型)
-
基本类型:由定义位置决定,函数体外的基本类型对象默认初始化为0;函数体内未定义
-
其他类型:由具体类的实现方式决定,String会被初始化为空串
-
-
列表初始化(基本类型&&存在丢失信息风险=》编译报错)
声明和定义区别:定义需要申请存储空间,可能还要进行初始化操作
如何表示声明?加extern关键字
int j;//定义
extern int j;//声明
为什么区分声明和定义?
为支持分离编译,多个文件要使用同一个变量就必须将声明和定义分离。a文件要用b文件定义的变量,必须声明一下那个变量。一个变量可以被声明多次,但是只能被定义一次。
引用作用域外的对象
int i = 42;
int main()
{
int i = 40;
std::cout << i << endl;//40
std::cout << ::i << endl; //42
}
2.3 复合类型
引用:对象的别名,本身不是对象。
指针:是对象,指向对象的地址。
类型 | 定义方式 | 类型要求 | 初始化要求 | 常见操作 |
---|---|---|---|---|
引用 | int &rval = val; | 除两种情况外,引用类型必须和对象类型相匹配(int类型的引用的右值必须是int类型) | 必须直接初始化右值不能是字面量 | 对rval操作就是在操作val引用是可以绑定到其他对象上的 |
指针 | int *p = &val | 除两种情况外,指针类型必须和对象类型相匹配(int类型的指针的右值必须是int类型) | 不必直接初始化,块作用域内定义的指针没有显示初始化会是一个不确定的值可使用nullptr初始化指针 | 解引用比较操作(地址相等返回true,指向某个对象和指向另外对象下一个地址也可能返回true) |
2.4 const限定符
常量,不可以被改变。
const对象必须被初始化,可以用const对象去初始化别人。
为什么const对象仅在文件内有效?
因为编译器会把const变量替换成常量 -> 编译器需要找到const变量的定义位置 -所以默认文件内有效。不同文件中定义的同名const变量被认为是独立的。
如何做到跨文件共享const变量?对const变量的声明和定义都加上extern。
初始化的常量引用和常量指针可以引用类型不相同的对象。
double d = 3.14;
const int & r = d;//可以,r的取值是3,存在精度损失
原因:编译时一旦出现类型不匹配,编译器的行为是先生成一个与引用/指针类型相同的临时量,然后让引用/指针去引用/指向这个临时量。对于非const的引用/指针,他们被绑给了一个临时量而不是原始对象,不符合语义,所以报错;对于const的引用/指针,反正也不会通过它们修改对象值,指向临时量和指向原始对象没差别,所以这种情况不会报错而是允许const引用/指针绑给一个精度出现损伤的临时量。
引用、指针与const的关系:
-
const引用/指针可以作为const对象的左值
-
非const引用/指针可以作为非const对象的左值
-
const引用/指针可以作为非const对象的左值
-
非const引用/指针不可以作为const对象的左值
上面关键在于第4点,const引用/指针可以引用非常量对象,只要不保证通过这个常量的引用/指针去改变对象就行,其他引用/指针修改对象也管不了;但是运行非const去引用const那就意味着允许通过它去修改对象,编译器会报错。
顶层const(int * const p):指针本身指向的地址不可以修改
底层const(const int * p):指针指向的地址的值不可以修改
执行拷贝操作时拷贝考出的对象要具备相同的底层const资格,这其实体现了上面那四条关系,避免拷贝时出现非const引用const的情况。
对常量的取址操作返回结果可以用什么引用?
const对象的取值只能用底层const引用
const double d = 3.14;
const double * p = &d;//ok
double * p = &d;//wrong
double * const p = &d;//wrong
常量表达式:编译时就能得到计算结果的表达式(字面值以及字面值初始化的const变量)。
下面的公式不是常量表达式,因为getSize需要运算才能得到结果
const int size = getSize();
如何声明一个常量表达式?
声明为constexpr后编译器会对getSize进行检查,如果getSize是constexpr函数的话拿它就是常量表达式
constexpr int size = getSize();
constexpr的作用范围:仅限字面值类型,包括算术类型、引用、指针等,不能用于声明string等自定义类型。
constexpr与指针:
-
指针可以声明为constexpr类型,它的语义是这个指针指向的位置不可变(顶层const)
-
constexpr指针的初始值受到严格限制,只能是0,nullptr或指向固定地址的指针(在函数方法里定义的指针指向位置经常变,不能声明为constexpr)
2.5 处理类型
定义类型别名
-
typedef关键字
-
using关键字
解读指针类型的别名是千万不要直接做个替换就开始读了!!!
str是什么类型?
typedef char* pstring;
const pstring str = 0;
不要解读为const char * str = 0;这样str就是指向char常量的指针了。实际情况是const是修饰char *的,表示这个指针是常量(顶层const),而不是指针指向的对象是const。
类型推断之auto:
让编译器去分析所属类型。一个auto语句后面可以声明多个变量,必须保证基本类型是一致的(比如同是int类型、int类型引用或int类型指针)
auto推断的两个特点:
-
auto a = r;r是引用类型时(int &),a会被推断为基本类型(int)
-
auto一般会推断出底层const,无法推断出顶层const,如要保留顶层const特性可以手动加const
const int p = 0;
int p3 = 0;
int const * pp = &p3;
const int & p2 = p;
auto d = p;//p是顶层const,这里的d丢失了顶层const特性,只是int类型
auto a = &p;//&p只能用const int引用,是底层const,底层const被保留,a是const int*类型
auto b = pp;//b是const int *类型,这里pp是顶层引用,但是也可以保留
auto c = p2;//c是int类型,顶层const信息丢失
const auto f = p2;//f是const int,手动加const
类型推断之decltype:
decltype(表达式) a,那么a就是表达式的返回类型。
它和auto的区别:
-
可以推断出引用类型(int &r = v;decltype(r) j;这里j是int &而不是int)
-
可以推断出顶层const
此外还有一些特点
-
decltype(引用和基本类型的算术表达式,如int & + 0),那么最后实际类型是基本类型
-
decltype(解引用操作),最后返回的是引用类型
练习2.37:decltype(a = b),实际上a = b并没有执行。
2.6 自定义数据结构
定义struct类型的方式。
使用头文件:在头文件中定义类,这样通过include头文件的方式就可在不同文件中使用这个类了。
预处理器:编译之前执行的一段程序,会改变我们所写的程序。它对头文件的影响:
-
对cpp文件:用头文件内容代替#include
-
对头文件:使用头文件保护符#define、#ifdef等,写在头文件的类的定义周围;避免头文件被重复定义。良好的代码习惯要求加上这些保护符。
预处理变量:不属于任何命名空间,前面无需加std::
标签:const,int,c++,对象,ch2,引用,类型,primer,指针 From: https://www.cnblogs.com/ljf-0/p/18041486