char * /字符串连接没有复制?

时间:2015-12-14 16:26:45

标签: c++ c string

我想在没有新的内存分配和复制的情况下在C或C ++中连接2个字符串。有可能吗?

可能的C代码:

char* str1 = (char*)malloc(100);
char* str2 = (char*)malloc(50);
char* str3 = /* some code that concatenates these 2 strings
                without copying to occupy a continuous memory region */

然后,当我不再需要它们时,我就这样做了:

free(str1);
free(str2);

或者如果可能的话,我希望在C ++中使用std::stringchar*来实现相同的目标,但使用newdelete(可能void operator delete ( void* ptr, std::size_t sz )在str3上运算符(C ++ 14)。

关于字符串连接有很多问题,但是我没有找到一个问题相同的问题。

4 个答案:

答案 0 :(得分:7)

不,不可能

在C中,malloc操作返回彼此没有关系的内存块。但在C语言中,字符串必须是连续的字节数组。因此没有办法在不复制的情况下扩展str1,更不用说连接了。

对于C ++,可能会对绳索感兴趣:See this answer

绳索以不必连续的块分配。这支持O(1)连接。但是,访问器使它显示为单个字节串。我确定将绳索转换回std :: string或C风格的字符串会占用一个副本,但这可能是你想要的最接近的。

此外,担心复制几个字符串的成本可能是一个不成熟的优化。除非您移动批次数据,否则无关紧要

答案 1 :(得分:2)

通过编写自己的字符串数据结构,可以实现文本连接。 C ++比C更容易。

struct My_String
{
  std::vector<char *> text_fragments;
};

您必须基于此数据结构实现所有文本操作和搜索算法。 C库中的任何内容都不能应用于My_String结构。 C ++中的std::string不兼容。

其中一个问题是如何处理文本修改。如果其中一个文本片段是常量文字(无法修改),则需要先复制它才能进行修改。但复制是违背要求的。 : - (

答案 2 :(得分:1)

C中的“字符串”是一个字符数组,末尾有一个空字符。数组是“一种数据结构,可以让你在内存中存储一​​个或多个连续元素”。 GNU C reference

如果不复制其中一个数组,则无法连接两个不在连续内存块中的数组。但是,您无需分配新内存即可。 E.g。

char* str1 = malloc(100);  // size 100 bytes, uninitialised
str1[0] = '\0';            // string length 0, size of str1 100
strcat(str1, "a");         // string length 1, size of str1 still 100
strcat(str1, "b");         // string length 2, size of str1 still 100

如果您想要检索2个字符串的字符,就好像它们是没有复制或重新分配的字符串一样。这是一个示例函数(简单示例,不要在生产代码中使用

char* str1 = (char*)malloc(100);
char* str2 = (char*)malloc(50);

char get_char(int i) {
    if (i > 0 && i < 100) {
        return str1[i];
    }
    if (i >= 100 && i < 150) {
        return str2[i-100];
    }
    return 0;
}

但在这种情况下,您无法使用char* str3执行指针算法并访问所有150个字符。

答案 3 :(得分:0)

标签C和C ++是矛盾的。在C中,我建议探索realloc。您可以按照以下方式编写代码:

char* str = malloc(50);
str = realloc(ptr, 55);

如果幸运的话,realloc调用将不会重新分配新内存,只是“扩展”已分配的段,但不保证这一点。这样你至少可以避免重新分配字符串。您仍然需要将第二个字符串的内容复制到neweley分配的内存中。