条目十三《尽量使用vector和string来代替使用数组》
数组在现代编程语言中基本都存在,应用可谓广泛,不可或缺,虽然在一些语言中(go)有切片等数据结构,但是数组还是存在的。
但是在有了stl后,在使用数组时更建议用vector和string来代替,因为在动态分配数组的内存时,需要人为的管理内存。比如在new T[]时,需要在用完分配的数组后先手工释放数组存放的对象,然后再释放数组的内存
直接使用数组的不好之处有:
- 在很多时候,如果程序运行时在动态分配数组内存后产生异常,那么就不会调用析构数组里的对象和释放内存,造成内存泄露。
- 数组不是根据存放元素动态增长的,所以在动态分配内存的时候很难把握分配内存的大小。而vector和string里头是分配子allocator来动态维护vector和string的内存空间的。
new T[...]
当T是char时有两种选择,其他时候用vector和string代替数组的选择是比较明确的,所以这里主要说说当T是char的情况。
new char[...]时可以用vector和string来代替。其实除了一种情况,其他时候基本是string代替数组的。所以直接说特殊情况就ok了。
string在底层的实现大多的厂商是实现了多线程安全的,一般是使用引用计数方法。所以在使用string的时候,不用担心线性安全的问题。但是如果你的生产环境不需要考虑线性安全的,string为了保证线性安全所做的工作就是多余的。
在这里,有几种方法可以修改string是非线性安全的:
- 1.查找厂商的文档资料,因为string的引用计数保证线性安全是一个优化,所以一般会重点标出的。而且一般有一个宏定义来开关。
- 2.自己追踪源码,这里注意string只是basic_string的一个typedef,所以使用在追踪源码的时候是查找basic_string的实现,主要是看构造函数是否有引用计数这个成员变量,如果有直接屏蔽掉对应的代码。
- 3.使用vector代替string。这一点就是上面说到的特殊情况。
如果想把老代码的接口的形参是数组的,而现在是想传其他容器进去,在这里也有办法,可以先把其他容器转换为vector或string,然后再传进去。过多的分析在后面的条目16会分析到。