如何从方法中删除分配的内存并仍然 return 它的值
how do I delete allocated memory and still return its value from method
我将此功能作为 class 的一部分,我正在写:
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;
}
如您所见,我的问题是我需要为传入的字符串动态分配缓冲区大小,我想 return 将该值提供给用户。我不想让用户不得不释放内存,因为这看起来封装很差。
我的直觉是为我的用户创建一个 incomingDataBuffer c 字符串的静态副本,return。然而,尽管进行了大量搜索,但我一直无法找到执行此操作的通用方法,这让我认为我可能只是采取了错误的方法。
显然我还有其他选择。
我可以使 incomingDataBuffer 成为 class 成员,然后在析构函数中处理它的删除,但这不知何故感觉不对,因为它没有其他理由成为 class 成员。
我想我可以遍历数组并将其转换为一个可以 returned 并转换为字符串的向量。但这同样感觉不太正确,因为 incomingDataBuffer 在某些情况下可能非常大,而且这种操作可能非常昂贵。
无论如何,我想这一定是标准方法的常见问题,那么正确的 c++ 方法是什么?
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 []
,并且从函数返回它不会复制数据(因为它只是 moved)。
标准的 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。
只需使用 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。
我将此功能作为 class 的一部分,我正在写:
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;
}
如您所见,我的问题是我需要为传入的字符串动态分配缓冲区大小,我想 return 将该值提供给用户。我不想让用户不得不释放内存,因为这看起来封装很差。
我的直觉是为我的用户创建一个 incomingDataBuffer c 字符串的静态副本,return。然而,尽管进行了大量搜索,但我一直无法找到执行此操作的通用方法,这让我认为我可能只是采取了错误的方法。
显然我还有其他选择。
我可以使 incomingDataBuffer 成为 class 成员,然后在析构函数中处理它的删除,但这不知何故感觉不对,因为它没有其他理由成为 class 成员。
我想我可以遍历数组并将其转换为一个可以 returned 并转换为字符串的向量。但这同样感觉不太正确,因为 incomingDataBuffer 在某些情况下可能非常大,而且这种操作可能非常昂贵。
无论如何,我想这一定是标准方法的常见问题,那么正确的 c++ 方法是什么?
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 []
,并且从函数返回它不会复制数据(因为它只是 moved)。
标准的 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。
只需使用 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。