cpp primer 第四章笔记
第四章主要是表达式相关的内容:
- 除了
&& || ?: ,四种操作符外,其他操作符都没有定义运算顺序(重要) sizeof是一种运算符,它不会对表达式进行求值,c++11允许用作用域运算符(::)来获取成员大小而不必提供一个实体(前提是,该成员是public的,活着调用方法是static的),对数组返回数组大小而不是指针大小,对vector和string这种返回其固定部分大小。
#include <iostream> #include <string> class testc{ public: char pwc; void update(){} private: char wc; }; int main(){ int a=44; int ar[5]; std::string str("heheda!"); std::cout<<"int : "<<sizeof(a)<<" "<<sizeof(int)<<std::endl; std::cout<<"int [5]: "<<sizeof(ar)<<" "<<sizeof(int [5])<<std::endl; std::cout<<"string :"<<sizeof(str)<<" "<<sizeof(std::string)<<std::endl; std::cout<<"class member(char): "<<sizeof(testc::pwc)<<std::endl; return 0; }$ ./sizeoftest.out int : 4 4 int [5]: 20 20 string :24 24 class member(char): 1逗号运算符先算左边再算右边,最后返回右边,若右边结果为左值则返回的也是左值
大多数情况下数组退化为指针,有四种例外:decltype、取址运算符(&),sizeof,typeid:
#include <iostream> int main(){ int a[4]; std::cout<<"int size: "<<sizeof(int)<<std::endl; std::cout<<"arr size: "<<sizeof(a)<<std::endl; std::cout<<"a[0] addr: "<<&a[0]<<std::endl; std::cout<<"a addr: "<<a<<std::endl; std::cout<<"&a :"<<&a<<std::endl; std::cout<<"&a[0]+1: "<<&a[0]+1<<std::endl; std::cout<<"a+1: "<<a+1<<std::endl; std::cout<<"&a+1: "<<&a+1<<std::endl; return 0; }$ ./arrayaddr.out int size: 4 arr size: 16 a[0] addr: 0x7fff566947e0 a addr: 0x7fff566947e0 &a :0x7fff566947e0 &a[0]+1: 0x7fff566947e4 a+1: 0x7fff566947e4 &a+1: 0x7fff566947f0可以发现当采取
&a+1这种形式时,与数组首地址相比,并不是单纯加4,而是加4*4,故而大胆推测,&a的类型为int [4](类似二维数组中的一维元素)指针的转换规则:
- 0和nullptr可以转换成任意指针(空指针)
- 任意非常量指针可以转换成
void* - 任意指针可以转换成
const void*
显示转换:
static_cast就相当于c的强制类型转换const_cast去除底层const属性,但是对转换后的对象(一般是指针,对其指向的对象)写操作是未定义的,而且不能改变变量类型reinterpret_cast最危险的转换,相当于对同一个内存的地址做不同意义的解释(比如把一个int*解释为一个char*),依赖于机器dynamic_cast将指向子类的父类型的指针转化为子类型,这个功能也可以由static_cast来实现,但是dy会在运行时检查父子类关系,而static只会在编译时检查
