【问题标题】:String.replace() and dynamic memoryString.replace() 和动态内存
【发布时间】:2016-07-19 11:50:43
【问题描述】:

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

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

我知道我一开始不应该使用 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; 
    }
}

【问题讨论】:

标签: c++ arduino


【解决方案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 参数等...

【讨论】:

    【解决方案2】:

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

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

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

    然而,所有这一切都需要处理 String 类的内部结构(包括调整内容的大小和可能的容量,如果由于太短而不得不重新分配自己的缓冲区),如果没有肮脏的黑客攻击,您将无法访问将在 String 类更改后立即中断...

    我的建议:相信 arduino 的实现——你应该假设它已经做了你正在尝试的事情:如果内部缓冲区足够长来保存整个结果,它将被使用(不需要移动或复制其中的字符串索引 0-s,将部分从 s+c 适当地移动到结束,然后复制 subout 的内容)和 only 使用重新分配,如果内部缓冲区 not 长足够的。

    【讨论】:

      猜你喜欢
      • 2013-05-08
      • 1970-01-01
      • 1970-01-01
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多