返回从缓冲区和函数中读取的字符串,而不进行动态分配

Return string read from buffer and function without dynamic allocation?

本文关键字:动态分配 字符串 缓冲区 函数 读取 返回      更新时间:2023-10-16

在没有动态分配内存的情况下,我该如何返回从函数内的缓冲区构建的字符串?

目前我有这个函数要考虑:

    // 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删除数据。我不认为有办法解决这个问题,但我不完全确定是否可能。

我个人建议只返回std::stringstd::vector<T>:这巧妙地避免了内存泄漏,字符串不会为小字符串分配内存(好吧,大多数实现都是这样做的,但不是所有的都有)。

另一种方法是创建一个类,它可以保存一个足够大的数组,并返回一个类型为:

的对象。
struct buffer {
     enum { maxsize = 16 };
     ubyte buffer[maxsize];
};

如果你想得到更多的花哨和支持更大的字符串,然后只是分配内存,你需要处理更多的构造函数,析构函数等(或只是使用std::vector<ubyte>和克服它)。

至少有三种方法可以重新实现该方法,以避免与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;
}

请注意,最后一个选项有一些限制,包括多线程应用程序中数据竞争的可能性,以及无法在递归函数中调用它,以及其他一些微妙的问题。但是,如果您采取一些预防措施并对调用代码进行一些假设,则可能是最接近您所寻找的,并且可以安全使用的。