CFixedStringT:自定义字符串管理器示例

ATL 库实现了类 CFixedStringT 使用的自定义字符串管理器的一个示例,称为 CFixedStringMgr。 CFixedStringT 派生自 CStringT 并实现一个字符串,只要该字符串小于 CFixedStringTt_nChars 模板参数指定的长度,就将其字符数据分配为 CFixedStringT 对象本身的一部分。 使用这种方法,字符串根本不需要堆,除非字符串的长度增长到超过固定缓冲区的大小。 由于 CFixedStringT 并不总是使用堆来分配其字符串数据,因此它不能用作 CAtlStringMgr 其字符串管理器。 它使用自定义字符串管理器 (CFixedStringMgr),实现 IAtlStringMgr 接口。 自定义字符串管理器的实现(高级方法)中讨论了此接口。

CFixedStringMgr 的构造函数接受三个参数:

  • pData:指向要使用的固定 CStringData 结构的指针。

  • nChars:CStringData 结构可以容纳的最大字符数。

  • pMgr:指向“备份字符串管理器”的 IAtlStringMgr 接口的指针。

构造函数将 pData 和 pMgr 的值存储在它们各自的成员变量(m_pDatam_pMgr)中。 然后它将缓冲区的长度设置为零,可用长度等于固定缓冲区的最大大小,并将引用计数设置为 -1。 引用计数值指示缓冲区已锁定,并将 CFixedStringMgr 的此实例用作字符串管理器。

将缓冲区标记为已锁定可防止其他 CStringT 实例持有对该缓冲区的共享引用。 如果允许其他 CStringT 实例共享缓冲区,则可能会删除 CFixedStringT 包含的缓冲区,而其他字符串仍在使用该缓冲区。

CFixedStringMgrIAtlStringMgr 接口的完整实现。 将单独讨论每个方法的实现。

CFixedStringMgr::Allocate 的实现

CFixedStringMgr::Allocate 的实现首先检查字符串的请求大小是否小于或等于固定缓冲区的大小(存储在 m_pData 成员中)。 如果固定缓冲区足够大,CFixedStringMgr 则锁定长度为零的固定缓冲区。 只要字符串长度不超过固定缓冲区的大小,CStringT 就不必重新分配缓冲区。

如果请求的字符串大小大于固定缓冲区 CFixedStringMgr,则会将请求转发到备份字符串管理器。 备份字符串管理器假定从堆分配缓冲区。 但是,在返回此缓冲区之前,CFixedStringMgr 会锁定缓冲区并将缓冲区的字符串管理器指针替换为指向 CFixedStringMgr 对象的指针。 这确保尝试通过 CStringT 重新分配或释放缓冲区时将调用 CFixedStringMgr

CFixedStringMgr::ReAllocate 的实现

CFixedStringMgr::ReAllocate 的实现与 Allocate 的实现非常相似。

如果被重新分配的缓冲区是固定缓冲区并且请求的缓冲区大小小于固定缓冲区,则不进行分配。 但如果重新分配的缓冲区不是固定缓冲区,则必须是使用备份管理器分配的缓冲区。 在这种情况下,备份管理器用于重新分配缓冲区。

如果被重新分配的缓冲区是固定缓冲区并且新缓冲区大小太大而无法容纳在固定缓冲区中,则 CFixedStringMgr 使用备份管理器分配新缓冲区。 然后,固定缓冲区的内容将复制到新缓冲区中。

CFixedStringMgr::Free 的实现

CFixedStringMgr::Free 的实现遵循与 AllocateReAllocate 相同的模式。 如果释放的缓冲区是固定缓冲区,则该方法将其设置为零长度锁定的缓冲区。 如果正在释放的缓冲区是由备份管理器分配的,则 CFixedStringMgr 使用备份管理器来释放缓冲区。

CFixedStringMgr::Clone 的实现

CFixedStringMgr::Clone 的实现总是返回一个指向备份管理器的指针,而不是 CFixedStringMgr 本身。 发生这种情况是因为 CFixedStringMgr 的每个实例只能与 CStringT 的单个实例相关联。 任何其他尝试克隆管理器的 CStringT 实例都应该获取备份管理器。 这是因为备份管理器支持共享。

CFixedStringMgr::GetNilString 的实现

CFixedStringMgr::GetNilString 的实现返回固定缓冲区。 由于 CFixedStringMgrCStringT 之间是一对一对应关系,因此给定的 CStringT 实例一次不会使用超过一个缓冲区。 因此,从不需要同时使用 nil 字符串和真正的字符串缓冲区。

每当固定缓冲区未使用时,CFixedStringMgr 可确保将其初始化为零长度。 这样,它就可以用作 nil 字符串。 作为额外的奖励,固定缓冲区的 nAllocLength 成员始终设置为固定缓冲区的完整大小。 这意味着在不调用 IAtlStringMgr::Reallocate 的情况下 CStringT 也会让字符串增长,即使对于 nil 字符串也是如此。

要求

标头:cstringt.h

另请参阅

使用 CStringT 进行内存管理