我有以下功能:
std::wstring GetNetStatus()
{
NETSETUP_JOIN_STATUS bufType;
::ZeroMemory(&bufType, sizeof(NETSETUP_JOIN_STATUS));
LPWSTR buf;
CHECK_OS_ERROR(::NetGetJoinInformation(nullptr, &buf, &bufType) == NERR_Success);
std::wstring group(buf);
::NetApiBufferFree(buf);
return group;
}
我需要返回一个LPWSTR
值但是根据我正在使用的API,我需要在离开函数范围之前释放这个指针。
将一个LPWSTR
值分配给STL字符串并将其返回或是否有其他一些技巧是否正确?
答案 0 :(得分:2)
您所展示的内容在技术上是正确的。
但是,请注意,当std::wstring
从buf
复制字符数据时,它会使 potential 引发异常,因此您应该准备好处理这是为了避免任何可能的内存泄漏。
您可以使用__try/__finally
:
std::wstring GetNetStatus()
{
std::wstring result;
NETSETUP_JOIN_STATUS bufType;
::ZeroMemory(&bufType, sizeof(NETSETUP_JOIN_STATUS));
LPWSTR buf;
CHECK_OS_ERROR(::NetGetJoinInformation(nullptr, &buf, &bufType) == NERR_Success);
try {
result = buf;
}
__finally {
::NetApiBufferFree(buf);
}
return result;
}
或者,您可以编写遵循RAII语义的自定义class
/ struct
:
template <typename T>
class NetApiBuffer
{
private:
T* m_buf;
NetApiBuffer(const NetApiBuffer &) {}
NetApiBuffer& operator=(const NetApiBuffer &) { return *this; }
public:
NetApiBuffer(T *buf = 0) : m_buf(buf) {}
~NetApiBuffer() {
::NetApiBufferFree(m_buf);
}
operator T*() { return m_buf; }
T** operator&() { return &m_buf; }
};
std::wstring GetNetStatus()
{
NETSETUP_JOIN_STATUS bufType;
::ZeroMemory(&bufType, sizeof(NETSETUP_JOIN_STATUS));
NetApiBuffer<WCHAR> buf;
CHECK_OS_ERROR(::NetGetJoinInformation(nullptr, &buf, &bufType) == NERR_Success);
return std::wstring(buf);
}
或者,如果您使用的是C ++ 11或更高版本,则可以将std::unique_ptr
与自定义删除器一起使用:
std::wstring GetNetStatus()
{
NETSETUP_JOIN_STATUS bufType;
::ZeroMemory(&bufType, sizeof(NETSETUP_JOIN_STATUS));
LPWSTR buf;
CHECK_OS_ERROR(::NetGetJoinInformation(nullptr, &buf, &bufType) == NERR_Success);
std::unique_ptr<WCHAR, decltype(&::NetApiBufferFree)> deleter(buf, &::NetApiBufferFree);
return std::wstring(buf);
}
答案 1 :(得分:0)
使用原始C样式字符串指针构建std::wstring
后,wstring
对象深层复制输入原始指针指向的字符串,所以你是安全地将wstring
对象返回给调用者。
您可以采取哪些措施来提高代码质量,将显式字符串内存释放调用替换为NetApiBufferFree
,并使用安全的RAII包装,例如使用std::unique_ptr
自定义删除,例如:
// LPWSTR buf;
// ...
//
// ::NetApiBufferFree(buf);
auto deleter = [](void* ptr) { ::NetApiBufferFree(ptr); };
std::unique_ptr<wchar_t, decltype(deleter)> autoDelete(buf, deleter);
您的整个功能代码可以像这样调整:
std::wstring GetNetStatus()
{
NETSETUP_JOIN_STATUS bufType;
::ZeroMemory(&bufType, sizeof(NETSETUP_JOIN_STATUS));
LPWSTR buf = nullptr;
CHECK_OS_ERROR(::NetGetJoinInformation(nullptr, &buf, &bufType) == NERR_Success);
// Safe RAII wrapper around NetApiBufferFree()
auto deleter = [](void* ptr) { ::NetApiBufferFree(ptr); };
std::unique_ptr<wchar_t, decltype(deleter)> autoDelete(buf, deleter);
return std::wstring(buf);
// NetApiBufferFree() *automatically* invoked at function exit
}