Exceptional C++ 学习笔记1

第一条 vector的使用

       1 v[i] 与 v.at[i]

       这个知识点主要是讲用[]和at访问vector元素的区别。如果[]的话,因为标准并没有要求它做范围检查,所以效率较高,但访问越界不会抛出异常,可能会产生未定义行为。如果是用at的话,该成员函数会进行下标越界检查,所以越界时会抛出异常out_of_range。

 

      2 调整vector大小 v.size()  v.capacipy()

       size是当前vector容器真实占用的大小,也就是容器当前拥有多少个元素。它没有告诉你容器为它容纳的元素分配了多少内存。

      capacity告诉你容器在它已经分配的内存中能容纳多少元素。 如果你想知道一个vector中有多少没有被占用的内存,你必须从capacity()中减去size()。如果size和capacity返回同样的值,容器中就没有剩余空间了,而下一次插入(通过insert或push_back等)会引发realloc(重新分配)。  

     当然,这两个属性还分别对应两个方法:resize()和reserve()。

       使用resize(n),容器内的对象内存空间是真正存在的。它会强制把容器改为容纳n个元素。调用resize之后,size将会返回n。如果n小于当前大小,容器尾部的元素会被销毁。如果n大于当前大小,新默认构造的元素会添加到容器尾部。如果n大于当前容量,在元素加入之前会发生重新分配。 

    使用reserve(n)仅仅只是修改了capacity的值,容器内的对象并没有真实的内存空间(空间是"野"的)。强制容器把它的容量改为至少n,提供的n不小于当前大小。这一般强迫进行一次重新分配,因为容量需要增加。(如果n小于当前容量,vector忽略它,这个调用什么都不做

下面用例子进行说明:

 

[cpp] view plain copy  在CODE上查看代码片派生到我的代码片

  1. #include <iostream>  
  2. #include <vector>  
  3.   
  4. using std::vector;  
  5. int main(void)  
  6. {  
  7.     vector<int> v;  
  8.     std::cout<<"v.size() == " << v.size() << " v.capacity() = " << v.capacity() << std::endl;  
  9.     v.reserve(10);  
  10.     std::cout<<"v.size() == " << v.size() << " v.capacity() = " << v.capacity() << std::endl;  
  11.     v.resize(10);  
  12.     v.push_back(0);  
  13.     std::cout<<"v.size() == " << v.size() << " v.capacity() = " << v.capacity() << std::endl;  
  14.   
  15.     return 0;  
  16. }  

运行结果为:(win 10 + VS2010)

 

 

   补充: 在STL中,拥有capacity属性的容器只有vector和string。

             与size相关的还有一个max_size,它是编译器最大的能申请到的元素个数,结果会是一个非常非常大的值。

              如果sizeof一个vector对象,结果会是多少呢?

             由于vector应该是从堆上分配内存,所以sizeof的大小与元素个数无关,只取决于vector里面存放的数据类型,该值应该是与编译器相关的。在win10+VS2013下测试结果是16。指的应该是vector的四个指针类型成员变量:iterator _First, _Last, _End;所以会有16个字节

     3 代码风格

  1.    (1)尽量做到const的正确性,如果迭代器没有用来修改vector的中的值,应当选用const_iterator相关引申:
  2. 类似于指针,const vector<int>::iterator中,const是修饰的迭代器,也就是是个常迭代器,一旦初始化比如=a.begin(),再不能更改它的值,比如赋值=a.end()是不行的,递增递减操作等都不允许。虽然类似指针,但指针是内置类型,所以编译器可以通过const的位置来判断是常指针还是指向常量的指针,而迭代器只是一个对象,所以编译器不能分辨,所以用const_iterator来取代指向常量的指针,使用它,你通过这个迭代器对迭代器所指向的内容进行改写是非法的。
  3.   尽量使用!=而不是<来比较两个迭代器
  4.   尽量用前缀形式的--和++
  5.   避免无谓的重复求值。这个我也经常做不到,但是这样可以少定义一个临时变量,当不要求效率时,我喜欢用重复求值。
  6.   尽量使用\n而不是endl。记住endl会刷新缓冲区,如果你不要求刷新的话,就用\n。
  7.  尽量使用标准库中的copy()和for_each(),而不是自己手写循环。

 

第2条 字符串格式化的“动物乐园”之一:sprintf

笔者简介:    

 sprintf()主要功能是把格式化的数据写入某个字符缓冲区

 

原型

int sprintf( char *buffer, const char *format, [ argument] … );

      

参数列表

bufferchar型指针,指向将要写入的字符串的缓冲区。

format:格式化字符串。

[argument]...:可选参数,可以是任何类型的数据。

返回值

返回写入buffer 的字符数,出错则返回-1. 如果 buffer 或 format 是空指针,且不出错而继续,函数将返回-1,并且 errno 会被设置为 EINVAL。

sprintf 返回被写入buffer 的字节数,结束字符‘\0’不计入内。即,如果“Hello”被写入空间足够大的buffer后,函数sprintf 返回5

作者对sprintf进行了评价:

1.易用性与清晰性都不错

2.效率最佳(我有好几次性能问题都是格式化引起的,当我可以保证不越界的情况下,我会毫不犹豫的用它

3.长度安全性(没有,是引起缓冲区溢出出错的原因之一)

4.类型安全性(没有,对于sprintf来说,类型错误就意味着运行时错误,而非编译错误。printf家族使用C的可变参数列表,C编译期间通常不检查这类实参列表的类型

5.模板亲和性(没有)

snprintf函数是sprintf函数的更加安全版本,考虑到字符串的字节数,防止了字符串溢出。函数形式为:int snprintf(char *restrict buf, size_t n, const char * restrict  format, ...);。最多从源串中拷贝n-1个字符到目标串中,然后再在后面加一个0。所以如果目标串的大小为n 的话,将不会溢出。

exceptional c++:47个c++工程难题、编程问题和解决方案(中文版)》讲述如何用标准c++进行企业级的软件开发,通过“问题/解答”的方式,启发读者思考,帮助了解隐藏在问题背后的设计思想,以及各种编程指导原则适用的场合。本书列出的条款涵盖了许多方面的主题,尤其对异常安全性、类和模块的合理设计,正确的代码优化,以及编写符合c++标准的可移植代码进行了深入的讨论。   《exceptional c++:47个c++工程难题、编程问题和解决方案(中文版)》适于有一定c++编程基础的读者阅读。 目录 《exceptional c++:47个c++工程难题、编程问题和解决方案(中文版)》 1 泛型程序设计与c++标准库 1 条款1:迭代器难度系数 1 条款2:大小写不敏感的字符串——之一 5 条款3:大小写不敏感的字符串——之二 9 条款4:可重用性最高的泛型容器——之一 12 条款5:可重用性最高的泛型容器——之二 13 条款6:临时对象 22 条款7:标准库的使用(或者,再论临时对象) 28 2 异常安全性相关的问题与技术 31 条款8:编写异常安全的代码——之一 32 条款9:编写异常安全的代码——之二 37 条款10:编写异常安全的代码——之三 40 条款11:编写异常安全的代码——之四 47 条款12:编写异常安全的代码——之五 50 条款13:编写异常安全的代码——之六 56 条款14:编写异常安全的代码——之七 62 条款15:编写异常安全的代码——之八 65 条款16:编写异常安全的代码——之九 68 条款17:编写异常安全的代码——之十 73 条款18:代码的复杂性——之一 75 条款19:代码的复杂性——之二 79 3 类的设计与继承 85 条款20:类的编写技巧 85 条款21:虚函数的重载 93 条款22:类之间的关系——之一 99 条款23:类之间的关系——之二 103 条款24:继承的使用和滥用 110 条款25:面向对象程序设计 121 4 编译器防火墙和pimpl惯用法 123 条款26:将编译期依赖性降到最低——之一 123 条款27:将编译期依赖性降到最低——之二 127 条款28:将编译期依赖性降到最低——之三 132 条款29:编译防火墙 135 条款30:fast pimpl惯用法 138 5 名字查找、名字空间和接口规则 148 条款31:名字查找与接口规则——之一 148 条款32:名字查找与接口规则——之二 152 条款33:名字查找和接口规则——之三 162 条款34:名字查找与接口规则——之四 167 6 内存管理 176 条款35:内存管理——之一 176 条款36:内存管理——之二 179 条款37:auto_ptr 186 7 误区、陷阱以及错误的惯用法 201 条款38:对象标识 201 条款39:自动转换 204 条款40:对象的生存期——之一 206 条款41:对象的生存期——之二 209 8 其他主题 219 条款42:变量的初始化 219 条款43:正确使用const 222 条款44:类型转换 231 条款45:bool 238 条款46:转调函数 242 条款47:控制流程 244 后记 254 参考书目 256
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值