简介
字符串块可用来存储多个字符串。字符串块有一个特点,当以const方式插入字符串时,若之前已经存在该字符串,则后插入的字符串不会开辟新的内存空间,只会指向之前的字符串,其实现原理为GStringChunk内部维护了一个hash表,当后插入的字符串为const方式插入,会从hash表中查找该字符串是否存在,若已存在,则不会重复插入。
数据结构
typedef struct _GStringChunk GStringChunk;
字符串块是一个不透明的数据结构,我们可以整体使用它,但无法单独访问其结构体成员。
函数列表
GStringChunk * g_string_chunk_new ()
gchar * g_string_chunk_insert ()
gchar * g_string_chunk_insert_const ()
gchar * g_string_chunk_insert_len ()
void g_string_chunk_clear ()
void g_string_chunk_free ()
函数功能分类
// 申请字符串块,如果某个字节比较大,则内存会自动扩展,不再是size,尚不明白size是单个字符串的长度还是总trunk的长度
GStringChunk *
g_string_chunk_new (gsize size);
// 向chunk插入一个字符串,插入的字符串占用新的内存,与g_string_chunk_insert_const不同,本接口不会查重,并且用本接口插入的字符串,用_insert_const函数也不会查出重复来。
gchar *
g_string_chunk_insert (GStringChunk *chunk,
const gchar *string);
// 与insert类似,但会查重,重复的字符串不会作为新内存插入,但可能会出现多个指针指向同一个内存字符串的情况。
gchar *
g_string_chunk_insert_const (GStringChunk *chunk,
const gchar *string);
// 当string有非结尾空字节时,此len保证拷贝的完整性
gchar *
g_string_chunk_insert_len (GStringChunk *chunk,
const gchar *string,
gssize len);
// 字符串块清空,清空之后就不能再安全地访问了
void
g_string_chunk_clear (GStringChunk *chunk);
// 字符串块释放,与new对应,不能单独对字符串进行释放,所有的字符串必须调用本接口一起释放
void
g_string_chunk_free (GStringChunk *chunk);
函数功能说明及综合演示
综合演示
代码演示:
源码见glib_examples\glib_gstringchunk\glib_gstringchunk_basic
#include <glib.h>
#define SIZE 5
struct _GStringChunk
{
GHashTable *const_table;
GSList *storage_list;
gsize storage_next;
gsize this_size;
gsize default_size;
};
static void
test_string_chunks (void)
{
int i = 0;
GStringChunk *sc = NULL;
gchar *str[SIZE];
g_printf("\n");
sc = g_string_chunk_new (4096);
str[0] = g_string_chunk_insert(sc, "AA");
str[1] = g_string_chunk_insert_const(sc, "AA");
str[2] = g_string_chunk_insert_const(sc, "BBBB");
str[3] = g_string_chunk_insert_const(sc, "BBBB");
str[4] = g_string_chunk_insert(sc, "CCC");
for(i=0;i<SIZE;i++) {
g_print("str[%d]: %s \n", i, str[i]);
}
g_print("chunk this_size=%d, storage_next=%d \n", (gint)sc->this_size, (gint)sc->storage_next);
g_string_chunk_clear(sc);
g_string_chunk_free(sc);
}
int main (int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
g_test_add_func("/string/test_string_chunks", test_string_chunks);
return g_test_run();
}
运行结果:
/string/test_string_chunks:
str[0]: AA
str[1]: AA
str[2]: BBBB
str[3]: BBBB
str[4]: CCC
chunk this_size=4096, storage_next=15
OK
运行结果分析:
g_string_chunk_insert_const插入相同字符串时是否会占用额外内存空间?
在解答这一疑问时,需要用到_GStringChunk结构体,其中的storage_next的值就是当前已经存的字节数,由于此结构体不透明,需要在测试例中自己定义了_GStringChunk结构体。
sc->storage_next
值为15,其计算方法如下:
str[0] = g_string_chunk_insert(sc, "AA");
// 3个字节
str[1] = g_string_chunk_insert_const(sc, "AA");
// insert插入的无法查到,因此还是需要占3个字节
str[2] = g_string_chunk_insert_const(sc, "BBBB");
// 5个字节
str[3] = g_string_chunk_insert_const(sc, "BBBB");
// 由于之前是const方式插入,此时发现重复,不再开辟内存,不占字节
str[4] = g_string_chunk_insert(sc, "CCC");
// 4个字节
因此3+3+5+4=15
可见,insert插入的,insert_const无法查到,insert_const多次插入同一个字符串,只会占用一份内存。