C++ Primer 读书笔记01


“C++ Primer”


变量声明和定义
  • 变量声明规定变量的类型和名字,使得名字为程序所知

  • 定义除了与声明相同的部分还申请了存储空间,也可能会为变量赋一个初始值

  • 变量能且只能定义一次,但是可以被多次声明

    如果想声明一个变量而非定义它,就在变量名前添加关键字extern

    extern int i;	// 声明 i 而非定义 i
    int j;	      // 声明并定义 j
    
const
  • const对象一旦创建后其值就不能再改变,所以const对象必须初始化

  • 默认情况下,const对象仅在文件内有效,当多个文件出现了同名的 const变量时,其实等同于在不同文件中分别定义了独立的变量

  • 如果想要让const在多个文件中共享,则对const变量不管是声明还是定义都需要添加extern关键字

    extern const int bufSize = fcn();	// file.cc 定义并初始化一个常量,该常量能被其他文件访问
    extern const int bufSiz;	// file.h 与 file.cc 定义的是同一个
    
    指针与 const
    • 指向常量的指针不能用于改变其对象的值

      const double pi = 3.14;
      double *ptr = π	// 错误
      const double *cptr = π
      *cptr = 4;	// 错误
      double dval = 3.14;
      cptr = &dval;	// 正确,允许另一个指向常量的指针指向一个非常量对象
      
    • const 指针

    int errNum = 0;
    int *const curErr = &errNum;	// curErr 将一直指向 errNum
    const double pi = 3.14;
    const double *const pip = π	// pi 是一个指向常量对象的常量指针
    
    • 顶层const:表示指针本身是个常量

    • 底层const:表示指针所指的对象是一个常量

数组与指针
  1. 数组指针

    int (*Parray)[10] = &arr;	// Parray 指向一个含有 10 个整数的数组
    int (&arrRef)[10] = arr;	// arrRef 引用一个含有 10 个整数的数组
    
  2. 指针数组

    int *ptrs[10];	// 含有 3 个整数的数组
    
begin 和 end (11)
int ia[] = {0,1,2,3};
int *beg = begin(ia);	// 指向 ia 首元素的指针
int *last = end(ia);	// 指向 ia 尾元素的下一位置的指针,这两个函数定义在 iterator 头文件中
左值
  1. 可以出现在 operator=左边

  2. 当对象被用作左值的时候,用的是对象的身份(在内存中的位置)

右值:
  1. 可以出现在 operator=右边

  2. 当一个对象被用作右值的时候,用的是对象的值(内容)

  3. 如果表达式的求值结果是左值,decltype作用于该表达式(不是变量)得到一个引用类型

    int *p = nullptr;
    decltype(*p) x;	// 解应用得到的结果是左值,所以 x 是 int&
    decltype(&p) y;	// 取地址运算符生成右值,所以 y 是 int**
    
赋值运算符
  1. 赋值运算符的结果是它的左侧运算对象,并且是一个左值

  2. 如果赋值运算符的左右两个运算对象类型不同,则右侧运算对象将转换成左侧运算对象的类型

  3. 赋值运算符满足右结合律

    int ival, jval;
    ival = jval = 1; // 正确
    
递增和递减运算符
  • 前置版本:首先将运算对象加1(或减1),然后将改变后的对象作为求值结果已左值返回,

  • 后置版本:也会将运算对象加1(或减1),但是求值结果是运算对象改变之前值的副本,是右值

  • 如非必须,否则不用递增和递减运算符的后置版本

成员访问运算符

点运算符与箭头运算符的关系:ptr->mem 等价于 (*ptr).mem

sizeof

sizeof是一个运算符而不是一个函数,返回一条表达式或者一个类型名字所占的字节数,返回值为 size_t类型。

Sales_data data, *p;
sizeof(Sales_data);	// 存储 Sales_data 类型的对象所占的空间的大小
sizeof(data);		    // data 的类型的大小,即 sizeof(Sales_data)
sizeof p;					 // 指针所占空间大小
sizeof *p;		      // p 所指类型的空间大小,即 sizeof(Sales_data)
sizeof data.revenue	// Sales_data 的 revenue 成员对应类型的大小
sizeof Sales_data&  // 即 sizeof(Sales_data)
  • 对数组执行size_of运算得到整个数组所占空间的大小,等价于对数组中所有的元素各执行一次size_of运算并将结果求和
  • string对象或者vector对象执行size_of运算只返回该类型固定部分的大小
  • 对引用类型执行 size_of运算得到被引用对象所占空间的大小
强制类型转换
  1. static_cast任何具有明确定义的类型转换,只要不包含底层 const都可以使用

    double slope = static_cast<double>(j) / i;
    
  2. const_cast只能改变运算对象的底层const(即指针指向的对象是一个常量)

    const char *pc;
    char *p = const_cast<char *>(pc); // 去掉了 const 属性
    
  3. dynamic_cast
    用于动态类型转换。只能用于含有虚函数的类,用于类层次间的向上和向下转化。只能转指针或引用。
    向上转换:指的是子类向基类的转换
    向下转换:指的是基类向子类的转换

范围 for
for (declaration : expression)
  statement

expression表示的必须是一个序列,如花括号括起来的初始值列表、数组、vector string等,这些类型的共同特点是拥有能返回迭代器的beginend成员

局部静态对象:将局部变量定义成 static 类型

局部静态对象在程序执行路径第一次经过对象定义语句时初始化,并且知道程序终止时才被销毁,在此期间对象所在的函数结束执行也不会对它有影响。

函数声明

类似于变量,函数只能定义一次,但是可以声明多次

initializer_list

一种标准库类型,用于表示某种特定类型的值的数组,定义在同名头文件中,和vector不同,initializer_list中的元素永远是常量值,无法改变。

列表初始化返回值(c++11)
vector<string> process() {
  // expected, actual 是 string 对象
  if(expected.empty())	return {};
  else if (expected == actual) return {"function", "okay"};
  else return {"function", expected, actual};
}
返回数组指针
int (*func(int i))[10];	// func 参数是 int ,返回一个指向大小为 10 的数组的指针
auto func(int i) -> int(*)[10]; 	// c++11 后等价的写法
constexpr

constexpr函数指能用于常量表达式的函数,该函数的返回类型及所有形参的类型都是字面值类型,且函数体中必须有且只有一条return语句

constexpr int new_sz() {return 42;}
constexpr int foo = new_sz();

foo初始化时,编译器把对constexpr的调用结果替换成其结果值,且constexpr函数被隐式的指定为内联函数

内联函数和constexpr函数可以多次定义,所以可以将其定义在头文件中

assert

assert是一种预处理宏,当assert(expr)求值为假时,assert输出信息并终止程序,否则声明也不做

如果定义了NDEBUG,则assert什么也不做,编译时可以使用CC -D NDEBUG main.c来定义预处理变量

assert应该仅用于验证那些确实不可能发生的事情

疑惑:
  1. 习题 6.14 迭代器为何不能作为引用传递
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

thewangcj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值