gpt4 book ai didi

pointers - 将 unique_ptr/shared_ptr 与 API 函数结合使用,通过指针将资源作为输出参数返回

转载 作者:行者123 更新时间:2023-12-01 22:19:04 34 4
gpt4 key购买 nike

我现在正在当前项目中 catch C++ 11/14 的内容。我在使用 unique_ptr/shared_ptr 和通过指针将资源作为输出参数返回的 API 函数时遇到问题。

让我们以 DsGetDcName(..., __out PDOMAIN_CONTROLLER_INFO* ppDCI) 为例。

在 c++11 之前,存在一种使用 Windows API 的广泛模式。我将有一个 RIIA 类,它保存 PDOMAIN_CONTROLLER_INFO,在析构函数中调用 NetApiBufferFree,并具有 PDOMAIN_CONTROLLER_INFO* operator&(),以便我可以编写:

info_ptr spInfo;
DsGetDcName(..., &spInfo);

现在,在 C++ 11/14 中,我看到很多文章提倡使用自定义删除器来以正确的方式释放资源的 unique_ptr/shared_ptr 。当资源作为右值从函数返回时,它确实工作得很好(LoadLibrary 就是一个很好的例子)。

我发现的一个解决方案是在 API 调用之后将原始指针附加到智能指针:

PDOMAIN_CONTROLLER_INFO pDCI = nullptr;
DsGetDcName(..., &pDCI);
std::unique_ptr<DOMAIN_CONTROLLER_INFO, decltype(&NetApiBufferFree)> spInfo(pDCI, &NetApiBufferFree);

但是,这不是我喜欢的方式。据我了解,新的智能指针并不是为处理 out 参数而设计的,可能是因为“安全第一”的方法。

这里真的能做点什么吗?也许某种仿函数类充当输出参数代理,以便我可以编写 DsGetDcName(..., &out_param(spInfo))

最佳答案

好吧,您可以制作一个临时包装器,它将在销毁时初始化您的 std::unique_ptr:

#include <windows.h>
#include <Dsgetdc.h>
#include <Lm.h>

#include <memory>

template<typename T, typename D>
struct OutParameterWrapper
{
OutParameterWrapper(std::unique_ptr<T, D>& Target) : m_Target(Target), m_pSource(nullptr)
{
}
~OutParameterWrapper()
{
m_Target.reset(m_pSource);
}
operator T**()
{
return &m_pSource;
}
std::unique_ptr<T, D>& m_Target;
T* m_pSource;
};

int main(int argc, char** argv)
{
std::unique_ptr<DOMAIN_CONTROLLER_INFO, decltype(&NetApiBufferFree)> spInfo(nullptr, NetApiBufferFree);
DsGetDcName(NULL, NULL, NULL, NULL, 0, OutParameterWrapper<DOMAIN_CONTROLLER_INFO, decltype(&NetApiBufferFree)>(spInfo));
return 0;
}

编辑

要进行自动推导并使其同时适用于 std::unique_ptrstd::shared_ptr,您可以执行以下操作:

#include <windows.h>
#include <Dsgetdc.h>
#include <Lm.h>

#pragma comment(lib, "Netapi32.lib")

#include <memory>

template<typename T, typename P>
struct OutParameterWrapper
{
OutParameterWrapper(P& Target) : m_Target(Target), m_pSource(nullptr)
{
}
~OutParameterWrapper()
{
m_Target.reset(m_pSource);
}
operator T**()
{
return &m_pSource;
}

P& m_Target;
T* m_pSource;
};

template<typename P>
OutParameterWrapper<typename P::element_type, P> MakeOutParameterWrapper(P& Target)
{
return OutParameterWrapper<typename P::element_type,P>(Target);
}

int main(int argc, char** argv)
{
std::unique_ptr<DOMAIN_CONTROLLER_INFO, decltype(&NetApiBufferFree)> spInfo(nullptr, NetApiBufferFree);
std::shared_ptr<DOMAIN_CONTROLLER_INFO> spInfo2(nullptr, NetApiBufferFree);
auto nResult = DsGetDcName(NULL, NULL, NULL, NULL, 0, MakeOutParameterWrapper(spInfo));
DsGetDcName(NULL, NULL, NULL, NULL, 0, MakeOutParameterWrapper(spInfo2));
return 0;
}

关于pointers - 将 unique_ptr/shared_ptr 与 API 函数结合使用,通过指针将资源作为输出参数返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31651925/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com