RAII,unique_ptr和out参数

Jas*_*ban 7 c++ winapi out-parameters dynamic-memory-allocation

我是一名试图学习C++ 11的C#开发人员.我正在尝试使用windns.h查询DNS.

我开始DnsQuery()并阅读,我需要释放结果记录输出参数DnsRecordListFree().C#方式可能是使用try-finally块来确保我释放资源,无论如何.

但是我了解到没有finally阻塞,并且windns.h真的应该与时俱进并实现符合RAII标准的接口(据我理解的典型建议).我试图创建一个RAII包装器类,而不是等待它发生,我试图使用析构函数调用DnsRecordListFree()并使用运算符重载转换来获取原始指针.

但我对如何正确使用此句柄或指针获取out参数感到困惑.在我研究的过程中,我学会了如何unique_ptr(我已经学过一些东西)可以与自定义删除器一起使用.

所以这是我迄今为止的简单代码.可能更多的错误不仅仅是这个,但我想我可以声明另一个PDNS_RECORD *presult并使用它作为out参数然后复制或移动或以其他方式将其值分配给a unique_ptr,但这听起来像是太多的工作/混乱.

在我看来,unique_ptr内部指针应该初始化为NULL,我应该能够以某种方式将指针的地址传递给out参数,这DNSQuery将更新原始值,当unique_ptr我的函数中的范围超出范围时,DnsRecordListFree()调用将自动制作.我不知道为了最小的正确/安全使用找出正确的组合.

#include <iostream>
#include <fstream>
#include <memory>
#include <Windows.h>
#include <WinDNS.h>

using namespace std;

auto pdnsDeleter = [&](PDNS_RECORD *ptr){ if (ptr) DnsRecordListFree(ptr); };

int main(int argc, char **argv)
{
    cout << "Hello World\n";

    std::unique_ptr<PDNS_RECORD*, decltype(pdnsDeleter)> results(0, pdnsDeleter);

    if (DnsQuery(L"google.com", DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, ??results??, NULL))
    {
        cout << "google.com -> " << ??results??;
    }

    cout << "Done\n";
    getchar();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

谢谢!

Mar*_*som 5

您可以花一整天时间尝试调整标准智能指针,或者您可以自己编写.他们并不难做,特别是如果你愿意作弊并允许访问原始指针本身.

struct DnsRAII
{
    PDNS_RECORD p;

    DnsRAII() : p(NULL) { }
    ~DnsRAII() { if (p != NULL) DnsRecordListFree(p, DnsFreeRecordList); }
};

DnsRAII results;
if (DnsQuery(L"google.com", DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &results.p, NULL))
// ...
Run Code Online (Sandbox Code Playgroud)