《C++编程风格(修订版)》——2.5 动态内存的一致性-阿里云开发者社区

开发者社区> 开发与运维> 正文

《C++编程风格(修订版)》——2.5 动态内存的一致性

简介:

本节书摘来自异步社区出版社《C++编程风格(修订版)》一书中的第2章,第2.5节,作者:【美】Tom Cargill,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.5 动态内存的一致性

C++编程风格(修订版)
在程序清单 2.2 的 string 类中仍然存在着一些问题和不一致的地方。其中,在动态内存管理 上的不一致性与我们在前面所看到的不一致性是一样的,都是严重的问题。对于所有动态分配的 内存,我们都需要回答两个问题:首先,动态内存是不是足够大以容纳将要存储的信息?其次, 是不是所有的动态内存都是可回收的?

在默认构造函数中分配的字符数组肯定可以容纳空字符串:
image

这个构造函数所基于的假设是:在创建对象时将会为字符串分配内存,并且这个内存足以 容纳在对象生存期内需要保存的任意字符串。成员函数 assign() 与这个假设也是一致的:
image

在 assign() 中调用 strcpy() 对参数字符串进行拷贝时,并没有考虑到目标字符数组的长度或 者大小。编写客户代码的程序员必须保证——在创建对象时,无论调用的是哪个构造函数——在 构造函数中所创建的数组必须能够容纳在 assign() 中复制的任意字符串。

然而,在成员函数 concat() 中采用了一种不同的方法:在创建每个字符串时,总是动态地决 定所需数组的精确大小。函数 concat() 忽略了在创建 string 对象时已经分配好的字符数组,即使 这个已分配的数组是足够大的:

image

在 assign() 和 concat() 这两个函数的表现行为上存在着不一致性。它们的区别在于,在为 string

对象设置新值时,是否会动态分配字符数组:assing() 永远不会分配,而 concat() 则总是会分配。

接口一致性
上面哪种控制数组大小的方法是更好的?和许多软件决策一样,没有哪种方法是绝对的“正 确”或者绝对的“错误”。这两种方法都有各自的优点。保持在构造函数中分配的数组不变(assign() 中的做法)是一种高效的方法,因为在后续的操作中就无需再调用内存分配函数。对每个字符串 值都动态地决定数组的大小(concat() 中的做法)则是一种更安全的方法,因为这种方法杜绝了 数组的“越界”行为。

这两种方法都可以用在类中,但我们只能使用其中的一种,以保持类一致性,而不应该将 这两种方法混合使用。否则,在使用这个类时,程序员将不得不去了解在接口中不同操作之间的 不同约定。如果一个程序员只使用过 concat(),并且知道了数组的大小是动态增长的,那么他就 会假定 assign() 也是同样的行为,因此,当在 assign() 中发生数组内存的越界问题时,他所感到 的沮丧应该是可以预见的。

类的接口定义应该是一致的——避免产生困惑。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章