我有以下功能:

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,我需要在离开函数范围之前释放该指针。

向STL字符串分配LPWSTR值并返回它是否正确,或者还有其他技巧吗?

最佳答案

您显示的内容在技术上是正确的。

但是,请注意,当std::wstringbuf复制字符数据时,它有可能引发异常,因此您应该准备处理该异常以避免任何可能的内存泄漏。

您可以使用__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);
}

07-24 18:25
查看更多