C++ primer 学习笔记(一个学过谭老师的C++书籍, 并在一年间间断使用过C++的码农)

1. 如果表达式里既有带符号类型又有无符号类型, 那么带符号数会自动地转换成无符号数。由于size()函数返回的是一个无符号整数,故如果一条表达式中已经有了size()函数,就不要再使用int了,这样可以避免混用int和unsigned可能带来的问题。

2. 应使用 nullptr 代替NULL。

3. 有两种方法可用于定义类型别名,传统的方法是使用关键字 typedef 。新标准规定了一种新的关键字using

    使用方法: using a = b; //a是b的别名

4. 类型说明符 auto,自动推断表达式的类型。

5. 类型指示符 decltype, 作用是选择并返回操作数的数据类型。

    切记:decltype((variable))(注意是双层括号)的结果永远是引用,而decltype(variable)结果只有当variable本事就是一个引用时才是引用。而如果表达式的内容是解引用操作,则将得到引用类型。如decltype(*p)的结果类型就是int&而非int。

6. 使用std::cin对string进行读取操作时,string对象对自动忽略开头的空白(即空格符、换行符、制表符等),并从第一个真正的字符开始读起,直到遇见下一处空白为止。

    当用getline(std::cin, line)从给定的输入流中读入内容,直到遇到换行符为止(注意:换行符也被读进来了),然后把所读的内容存入line这个string对象中去(注意:不存换行符)。

    当对string对象使用 "+" 运算符时,必须确保“+”两侧的运算对象至少有一个是string。

7. 如果使用范围for语句改变字符串中的字符, for (auto &c : s);//c必须是引用

8. vector对象能高效增长,故在定义vector对象的时候没必要设定其大小,事实上如果这么做性能可能更差。只能对确知已存在的元素执行下标操作,确保下标合法的一种有效手段就是尽可能使用范围for语句。

9. 如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器。

10. 为了便于专门得到const_iterator类型的返回值,C++11新标准引入了两个新函数cbegincend

11. 凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素。

12. 不存在引用的数组,如:int &refs[10] = 是错误的。

13. 尽管C++支持C风格字符串,但在C++程序中最好不要使用它们。它们极易引发程序漏洞,是诸多安全问题的根本原因。

14. 严格来说,C++语言中没有多维数据,通常所说的多维数据其实是数组的数组。

15. 代码调试帮助:

assert预处理宏,NDEBUG预处理变量。使用#define NDEBUG可关闭调试状态。

编译器定义的局部静态变量:

1)__FILE__ :存放文件名的字符串字面值

2)__LINE__ :存放当前行号的整形字面值

3)__TIME__:存放文件编译时间的字符串字面值

4)__DATE__ :存放文件编译日期的字符串字面值

5)__func__:编译器定义的一个局部静态变量,用于存放函数的名字

16. 左值右值

书上这么归纳:当一个对象被用作右值的时候,用的的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。

网上总结的也挺好:左值右值的形式区分(或者称语法区分)是能否用取地址&运算符;语义区分(即其本质涵义)在于表达式代表的是持久对象还是临时对象。

17. 优先级规定了运算对象的组合方式,但是没有说明运算对象按照什么顺序求值。在大多数情况下,不会明确指定求值的顺序。

如:int i = f1() * f2(); 我们无法知道是f1和f2哪个先被调用。<<运算符也没有明确规定何时以及如何对运算对象求值。=赋值也是,没有明确说明先求左侧还是右侧的值。

只有4种运算符明确规定了运算对象的求值顺序。逻辑与&&, 逻辑或||, 条件运算符?:,逗号运算符,。

18. if ( val == true){ };  如果val不是布尔值,那么进行比较之前会首先把true转换成val的类型,注意不是把val转换成true类型,故只有当val等于1时条件才为真!

19. i++,++i。前置版本的递增运算符避免了不必要的工作,它把值加1后直接返回改变了的运算对象。与之相比,后置版本需要将原始值存储下来以便返回这个未修改的内容。

如果我们不需要修改前的值,那么后置版本的操作就是一种浪费。

20. 对于位运算,关于符号位如何处理没有明确的规定,所以强烈建议仅将位运算符用于处理无符号类型。

21. 逗号运算符,首先求左侧表达式的值,然后将该值丢弃掉。逗号运算符真正的结果是右侧表达式的值。

22. 如果有需要,尽量使用引用,以避免拷贝所带来的开销。

23. 数组的两个特殊性质对我们定义和使用作用在数组上的函数有影响,这两个性质分别是:

        1)不允许拷贝数组。指的是不能直接以数组名进行拷贝。

        2)使用数组名时(通常)会将其转换成指针。

24. 顶层const表示指针本身是个常量,而底层const表示指针所指的对象是一个常量。

如:int i = 0;

int *const p1 = &i;//不能改变p1的值,这是一个顶层const

const int ci = 42;//不能改变ci的值,这是一个顶层const

const int *p2 = &ci;//允许改变p2的值,这是一个顶层const

25. 重载和const形参

一个拥有顶层const的形参无法和另一个没有顶层const的形参区分开:

A look(int x);和A look(const int x);其实是等价的。

然而,如果形参是某种类型的指针或引用,则通过区分其指向的是常亮对象还是非常量对象可以实现函数重载,此时的const是底层的:

A look(int &x);和A look(const int &x);是不等价的,A look(int *x);和A look(const int *x);也是不等价的。

26. constexpr函数被隐式地指定为内联函数。

27. default:如果我们需要默认的行为,那么可以通过在参数列表后面写上=default在要求编译器生成构造函数。如果=default在类的内部,则默认构造函数是内联的;如果它在类的外部,则默认情况下不是内联的。

28. 如果成员是const、引用,或者属于某种未提供默认构造函数的类类型,我们必须通过构造函数初始值列表为这些成员提供初始值。

29. endl:完成换行并刷新缓冲区。

flush:刷新缓冲区,但不输出任何额外的字符。例如:cout << "hi" << flush;

ends:向缓冲区插入一个空字符,然后刷新缓冲区。

30. unitbuf操纵符:它告诉流在接下来的每次写操作之后都进行一次flush操作。

nounitbuf操纵符:重置流,使其恢复使用正常的系统管理的缓冲区刷新机制。

警告:如果程序崩溃,输出缓冲区不会被刷新。

当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流。

31. forward_list和array是新C11++标准增加的类型。通常,使用vector是最好的选择,除非你有很好的理由选择其他容器。

32. 在容器中访问元素的成员函数(即,front、back、下标和at)返回的都是引用

33. 强烈建议使用智能指针。最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准库函数。

待续。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值