C++ Primer学习笔记(更新中……)

第1章:开始

第2章:变量和基本类型

2.3符合类型

  • &、* 意义判断
    • 在声明中:构成符合类型(引用、指针)
    • 在表达式中:运算符(去地址、解引用)

2.3.1 引用

2.3.2 指针

2.4 const限定符

2.4.3 顶层const
  • 顶层const:本身是常量,例如const指针(int *const p ,这里的const是顶层const,指针p不可以改变)
  • 底层const:所指向的对象是常量(const int *p,指针p可以改变,指向的量不可以改变)

第3章:字符串、向量和数组

3.4 迭代器介绍

  • string、vector都支持下标和迭代器运算
3.4.1 使用迭代器
  • begin()与end()函数
vector<int> v;
const vector<int> cv;
auto it1 = v.begin();     //it1的类型是vector<int>::iterator
auto it2 = cv.begin();   //it2的类型是vector<int>::const_iterator
  • cbegin()和end()专门得到const_iterator类型

3.5 数组

3.5.1. 定义和初始化内置数组
  • 实时性较好,但灵活性较差
  • 数组维度必须是常量
  • 不可使用auto推断
  • 数组允许拷贝和赋值,不能使用一个数组初始化另一个数组,也不能用数组为其他数组赋值
  • 维度 >= 初始值总数量
  • 指针数组与数组指针
    • 指针数组:是数组,存放指针的数组(例如:int *ptrs[10]; ptrs是含有10个整型指针的数组)【从右往左阅读】
    • 数组指针:是指针,指向数组的指针(例如 :int (*parry)[10] = &arr; parry指向一个含有10个整数的数组)【从内往外阅读】
    • 例子:int *(&array) [10] = pts; // array是数组的引用,该数组含有10个指针
3.5.2 访问数组的元素
  • size_t类型定义数组下标(机器相关的无符号类型)
3.5.3 指针和数组
  • 数组会转换成指针,替换成指向数组首元素的指针
  • 取地址符(&)可以用于数组(取地址符可用于任何对象)
  • auto与decltype用于数组时的区别
    • auto:用其推断得到指针
    • decltype:用其推断得到数组
  • 指针也是迭代器
  • begin()与end()
    不是成员函数,将数组作为他们的参数进行使用(与3.4.1节的区别)
int ia[] = {0,1,2,3,4,5};
int *beg = begin(ia);
int *last = end(ia);
  • 指针加上加上某整数值,结果是指针
int arr[5] = {1,2,3,4,5};
int *ip = arr;             //等价于int  *ip + &arr[0]
int *ip2 = ip+4;        //ip2指向arr的尾元素arr[4]

第4章:表达式

4.1 基础

4.1.1基本概念
  • 左值和右值
    • 当一个对象被当作右值的时候,用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置——地址)。
    • 左值可以当成右值使用,但是右值不能当成左值使用。
      博客:左值与右值

4.5 递增和递减运算符

  • 一般使用前置版本
    • 后置与前置的区别
      • 后置:先赋值,再自增
      • 前置:先自增,再赋值
  • 混用解引用和递增运算符
    后置递增运算符优先级 > 解引用运算符
int arr[] = {1, 2, 3, 4};
int *p = arr;
int a = *p++; //等价于a = *(p++); 即a = *p = 1; p = p + 1,*p=2;
int b = *++p; //等价于b = *(++p) ; 即p = p + 1; b = *p = 3;
  • 在程序中,一般使用*p++,简洁
cout << *iter++ << endl;     //等价于cout << *iter <<endl;  ++iter;
4.11.3 显式转换
  • 命名的强制类型转换 ( 注意:避免强制类型转换,只有在函数重载的上下文中使用const_cast合适,其他情况尽量不要使用
    形式:cast-name< type >(expression)(注意:若type是引用类型,结果是左值)
    • static_cast:任何具有明确定义的类型转换,但不包含底层const
      • 适用场景:
        • 把较大的算术类型赋值给较小的类型
        • 当编译器无法自动执行的类型转换(例如:找回存在于void*指针的值)
    • const_cast:改变运算对象的底层const
      • 使用对象:
        • 不是常量:获得写权限是合法行为
        • 常量:执行写操作产生未定义的后
      • 使用场景
        如果有一个函数,它的形参是non-const类型变量,而且函数不会对实参的值进行改动,这时我们可以使用类型为const的变量来调用函数,此时需要使用const_cast
        常用于有函数重载的上下文中
    • dynamic_cast
    • reinterpret_cast:通常为运算对象的为模式提供较低层次上的重新解释

4.12 运算符优先级表

第5章:语句

第6章:函数

6.1 函数基础

6.2参数传递

  • 传值参数:函数对形参的操作不会影响实参
    • 指针形参:形参的指针和实参指针,形参的指针是实参指针的拷贝,是两个不同的指针指向相同的值,形参指针的值(地址)改变并不会影响实参的值,改变形参指向对象的值会改变是实参指针指向对象的值
#reset函数接受一个指针,将指针指向的值置为9,并将指针置为0
void reset( int *ip)
{  *ip = 9;
   ip = 0;   //只改变了ip的局部拷贝,实参未被改变
}  

int i = 42;
reset(&i);    //改变i的值而非i的地址
cout << i << endl;  //i=9
  • 传引用参数:引用形参,改变实参
    • 好处:
      • 避免拷贝:拷贝效率低,且有些类类型不支持拷贝
      • 返回额外信息:
  • 建议使用引用类型的形参,代替指针

6.3 返回类型和return语句

  • return拥有两种类型
    • return;( 只能用于void函数)
    • return expression;
      • 用于void函数中
        • 用于函数中部:提前结束函数(相当于break语句);
        • 用于函数尾部: expression必须是一个返回void的函数
      • 用于非void函数中(此函数必须拥有返回值。main函数除外,因为编译器隐式的插入返回0的return语句)
        • expression类型必须和函数的返回类型相同或能隐式转换
    • 不要返回局部对象的引用或指针(会引发错误)
6.3.3 返回数组指针

因为数组不能被拷贝,所以不能返回数组。但是函数可以返回数组的指针或者引用

  • 定义返回数组的指针或者引用的函数
    • 使用类型别名
    • 不适用类型别名
    • 使用尾置返回类型(个人觉得比较好用)
    • 使用decltype(已知返回的指针指向某个数组)
#类型别名
using arrT = int[10];
arrT* func(int i);
#什么也不用
int (*func(int i))[10];
#尾置返回
auto func(int i) -> int(*)[10];
#使用decltype
int odd[] = {1,3,5,7,9};
int even[] =  {0,2,4,6,8};
decltype(odd) *arrPtr(int i)
{return (i%2) ? &odd: &even;}

6.4 函数重载

  • 函数名相同,形参列表不同
  • 顶层const不影响参数传递,底层const会影响
    • 拥有顶层const与没有顶层const形参无法区分
  • 只通过函数返回值类型不同来进行函数重载会失败
  • 重载与作用域
    不要定义局部函数声明,调用函数会隐藏全局函数

第7章:类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值