我知道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;
}
}
答案 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& /*...*/
)传递,这可以避免复制这两个字符串。
char buff[len]
,仅在C中(从C99开始),请参阅e。 G。 here。您必须在堆上分配数组(new char [len]) - 除非您的编译器支持堆栈上的动态数组作为扩展。
然后你可以尝试重用in
字符串的缓冲区,但这只适用于你的替换字符串不长于要替换的字符串(更确切地说:更长的部分必须适合String内部分配的缓冲区用于保存内容,并且可能比后者长。在插入替换部分之前,您必须移动要替换的部分之后的字符串部分(例如使用memmove)。
然而,所有这些都需要处理String类的内部(包括例如调整内容的大小和可能的容量,如果你因为太短而不得不重新分配缓冲区)你没有访问权限没有脏的黑客攻击会在String类更改后立即中断......
我的建议:相信arduino的实现 - 你应该假设它已经是你正在尝试的:如果内部缓冲区足够长以容纳整个结果,它将被使用(不需要移动或如果内部缓冲区不< / em>足够长。