String.replace()和动态内存

时间:2016-03-31 07:06:48

标签: c++ arduino

我知道Arduino的String.replace函数使用realloc()。

我的“替换”函数是构建一个char缓冲区,然后将它分配给输入String,在动态内存分配方面是否更好?

我知道我不应该首先使用String,但我暂时坚持使用它。

这是我的功能:

void replaceSubstr(String& in, String subin, String subout){

    int s = in.indexOf(subin);

     if(s > -1)
    {
     int a = in.length();
     int b = subout.length();
     int c = subin.length(); 
     int len = (a + (b - c))+1;

    char buff[len];  
    memcpy(buff, in.c_str(), s);
    memcpy(&buff[s], subout.c_str(), b);
    memcpy(&buff[s+b], in.substring(s+c).c_str(), a-(s+c));

     buff[len-1] = '\0';
     in = buff; 
    }
}

2 个答案:

答案 0 :(得分:1)

来源

String::String(const char *cstr)
{
    init();
    if (cstr) copy(cstr, strlen(cstr));
}
...
inline void String::init(void)
{
    buffer = NULL;
    capacity = 0;
    len = 0;
}
...
String & String::copy(const char *cstr, unsigned int length)
{
    if (!reserve(length)) {
        invalidate();
        return *this;
    }
    len = length;
    strcpy(buffer, cstr);
    return *this;
}
...
void String::invalidate(void)
{
    if (buffer) free(buffer);
    buffer = NULL;
    capacity = len = 0;
}
...
unsigned char String::reserve(unsigned int size)
{
    if (buffer && capacity >= size) return 1;
    if (changeBuffer(size)) {
        if (len == 0) buffer[0] = 0;
        return 1;
    }
    return 0;
}

您的一行分配

 in = buff; 

也进行所有分配。

必须完成,原始String无法在不同的内存模型中保存buffer,只有一个“动态分配”有意义。

从广义的角度来看,许多C内存模型(堆栈,静态,由new分配,如果它们不同,由calloc分配)必须在现实生活库中减少 - 混合是危险的。例如,堆栈变量不能长寿 - 必须复制到“已分配”。

你检查新的可能性,这很好,但我同意Aconcagua对实施的信任,而不是取代原始的内存模型。

资料来源:https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/WString.cpp

编辑:同意const论点等......

答案 1 :(得分:0)

从效率的角度来看,你可以将subin和subout作为const引用(String const& /*...*/)传递,这可以避免复制这两个字符串。

C ++中不支持

char buff[len],仅在C中(从C99开始),请参阅e。 G。 here。您必须在堆上分配数组(new char [len]) - 除非您的编译器支持堆栈上的动态数组作为扩展。

然后你可以尝试重用in字符串的缓冲区,但这只适用于你的替换字符串不长于要替换的字符串(更确切地说:更长的部分必须适合String内部分配的缓冲区用于保存内容,并且可能比后者长。在插入替换部分之前,您必须移动要替换的部分之后的字符串部分(例如使用memmove)。

然而,所有这些都需要处理String类的内部(包括例如调整内容的大小和可能的容量,如果你因为太短而不得不重新分配缓冲区)你没有访问权限没有脏的黑客攻击会在String类更改后立即中断......

我的建议:相信arduino的实现 - 你应该假设它已经是你正在尝试的:如果内部缓冲区足够长以容纳整个结果,它将被使用(不需要移动或如果内部缓冲区不< / em>足够长。