2015-06-21 119 views
3

返回它的价值我有这个功能作为一个阶级的一部分,我写:如何删除分配的内存,并且仍然从方法

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 + +方式?

回答

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 d。

+0

谢谢,但这导致我第二个问题...我真的想要返回一个const char *,以便我可以cout <<我的返回值,但vector不像char [] –

+0

@SamRedway,没有已定义的流函数您可以使用'std :: string'来代替。 'std :: string'和'vector '就这个问题非常相似 - 两者都只是为你管理内存的'char'动态容器。 – Barry

+0

@SamRedway或者你可以用''vector'' ['cout.write()'](http://en.cppreference.com/w/cpp/io/basic_ostream/write)。 – Barry

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 []在它的析构函数,以及函数返回它没有数据的拷贝(因为它仅仅是移动)。

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; 

这样的内存是动态free'd。随着C++ 11和移动语义,也不会有昂贵的向量副本。一般来说,尽量避免在现代C++中显式的new/delete,这就是STL容器的用途。

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

相关问题