如何删除已分配的内存并仍然从方法

时间:2015-06-21 19:13:07

标签: c++ dynamic-arrays c-strings

我将此功能作为我写作课程的一部分:

const char* sockets::TCPSocket::doRecv(int flags)
{
    char* incomingDataBuffer = new char [this->bufferSize];
    ssize_t bytesReceived    = recv(this->filedes, incomingDataBuffer, this->bufferSize, flags);

    // TODO set timeout - If no data arrives, the program will just wait here until some data arrives.
    if (bytesReceived == 0 || bytesReceived == -1)
    {
        // TODO error handling
    }

    // TODO avoid memory leak
    // delete[] incomingDataBuffer;
    // incomingDataBuffer = 0;


    return incomingDataBuffer;
}

正如您所看到的,我的问题是我需要为传入的字符串动态分配缓冲区大小,我想将该值返回给用户。我不想让用户必须释放那些内存,因为这似乎是不好的封装。

我的直觉是创建incomingDataBuffer c字符串的静态副本并将其返回给我的用户。然而,尽管进行了一些沉重的搜索,我仍然无法找到一种常用的方法,这使我认为我可能只是采取了错误的方法。

显然我还有其他选择。

  • 我可以使incomingDataBuffer成为一个类成员,然后在析构函数中处理它的删除,但是这种方式感觉不对,因为它没有其他理由成为类成员。

  • 我想我可以遍历数组并将其转换为可以返回并转换为字符串的向量。但是,这并不是很正确,因为incomingDataBuffer在某些情况下会非常大,而且这种行为可能非常昂贵。

无论如何,我想这一定是标准方法的常见问题,那么正确的c ++方式是什么?

3 个答案:

答案 0 :(得分:1)

标准的C ++方式是使用std::vector

std::vector<char> sockets::TCPSocket::doRecv(int flags)
{
    std::vector<char> incomingDataBuffer(this->bufferSize);
    ssize_t bytesReceived = recv(this->filedes, 
        &incomingDataBuffer[0], this->bufferSize, flags);

    // TODO set timeout - If no data arrives, 
    // the program will just wait here until some data arrives.
    if (bytesReceived == 0 || bytesReceived == -1)
    {
        // TODO error handling
    }

    // on success, do this so that call site knows how much data
    // there actually is
    incomingDataBuffer.resize(bytesReceived);
    return incomingDataBuffer;
}

由于vector管理其内存,因此这里没有内存泄漏问题。通过返回它,您只需将内存管理的责任转移给调用者 - 但调用者不必执行任何特殊操作。当vector超出范围时,内存将自动delete

答案 1 :(得分:0)

C ++的方式是使用std::unique_ptr[]

std::unique_ptr<const char[]> sockets::TCPSocket::doRecv(int flags)
{
    std::uniqure_ptr<char[]> incomingDataBuffer(new char [this->bufferSize]);
    ssize_t bytesReceived    = recv(this->filedes, incomingDataBuffer.get(), this->bufferSize, flags);


    return incomingDataBuffer;
}

std::unique_ptr<char[]>在它的析构函数中执行delete [],并且从函数返回它不会复制数据(因为它只是移动)。

答案 2 :(得分:0)

只需使用std::vector<char>而不是动态分配的缓冲区:

std::vector<char> incomingBuffer(this->bufferSize);
ssize_t bytesReceived    = recv(this->filedes, incomingDataBuffer.data(), this->bufferSize, flags);
// Other stuff
return incomingBuffer;

这样,一旦向量在客户端留下范围,内存就会动态释放。使用C ++ 11和移动语义,也不会有昂贵的向量副本。一般来说,尽量避免使用现代C ++中的显式new / delete,这就是STL容器的用途。

只是为了完整性:另一种选择是使用std::unique_ptr<char[]>,但对于数组,我认为它的语法不如std :: vectors。