如何在不动态分配内存的情况下返回从函数中的缓冲区构建的字符串?
目前我有这个功能要考虑:
// Reads null-terminated string from buffer in instance of buffer class.
// uint16 :: unsigned short
// ubyte :: unsigned char
ubyte* Readstr( void ) {
ubyte* Result = new ubyte[]();
for( uint16 i = 0; i < ByteSize; i ++ ) {
Result[ i ] = Buffer[ ByteIndex ];
ByteIndex ++;
if ( Buffer[ ByteIndex - 1 ] == ubyte( 0 ) ) {
ByteIndex ++;
break;
};
};
return Result;
};
虽然我可以返回构建的字符串,但我无法在没有动态分配的情况下执行此操作。如果您考虑以下用法,这将成为一个问题:
// Instance of buffer class "Buffer" calling Readstr():
cout << Buffer.Readstr() << endl;
// or...
ubyte String[] = Buffer.String();
类似于此调用的用法导致相同的内存泄漏,因为数据未通过delete
删除。我不认为有办法解决这个问题,但我不完全确定它是否可行。
答案 0 :(得分:5)
就个人而言,我建议只返回std::string
或std::vector<T>
:这样可以避免内存泄漏,并且字符串不会为小字符串分配内存(嗯,大多数实现都在进行那种方式,但并非所有都在那里)。
另一种方法是创建一个类,该类可以容纳足够大的数组并返回一个类型为
的对象struct buffer {
enum { maxsize = 16 };
ubyte buffer[maxsize];
};
如果你想获得更多花哨并支持更大的字符串,然后只需分配内存,你需要更多地处理构造函数,析构函数等(或者只使用std::vector<ubyte>
并克服它)。
答案 1 :(得分:1)
至少有三种方法可以重新实现该方法,以避免使用new
进行直接分配。
使用std::vector
(这将分配堆内存):
std::vector<ubyte> Readstr()
{
std::vector<ubyte> Result;
for (uint16 i = 0; i < ByteSize; i++)
{
Result.push_back(Buffer[ByteIndex]);
ByteIndex++;
if (Buffer[ByteIndex - 1] == ubyte(0))
{
ByteIndex++;
break;
}
}
return Result;
}
强制调用者提供输出缓冲区,可能的大小确实避免溢出(不直接分配内存):
ubyte* Readstr(ubyte* outputBuffer, size_t maxCount)
{
for (uint16 i = 0; i < ByteSize; i++)
{
if (i == maxCount)
break;
outputBuffer[i] = Buffer[ByteIndex];
ByteIndex++;
if (Buffer[ByteIndex - 1] == ubyte(0))
{
ByteIndex++;
break;
}
}
return outputBuffer;
}
<丑陋:
使用内部静态数组并返回对它的引用:
ubyte* Readstr()
{
enum { MAX_SIZE = 2048 }; // Up to you to decide the max size...
static ubyte outputBuffer[MAX_SIZE];
for (uint16 i = 0; i < ByteSize; i++)
{
if (i == MAX_SIZE)
break;
outputBuffer[i] = Buffer[ByteIndex];
ByteIndex++;
if (Buffer[ByteIndex - 1] == ubyte(0))
{
ByteIndex++;
break;
}
}
return outputBuffer;
}
请注意,最后一个选项有一些限制,包括多线程应用程序中数据争用的可能性以及无法在递归函数中调用它,以及其他细微问题。但是,否则,可能是最接近您正在寻找的内容,并且如果您采取一些预防措施并对调用代码做出一些假设,则可以安全地使用。