RAII, unique_ptr, and out parameters
RAII, unique_ptr, and out parameters
我是一名c#开发人员,正在学习c++ 11。我正在尝试使用wins .h.
查询DNS。我从DnsQuery()
开始,读到我需要用DnsRecordListFree()
释放结果记录输出参数。c#的方法可能是使用try-finally
块来确保无论如何都可以释放资源。
但是我了解到没有finally
块,并且wind .h确实应该与时俱进并实现符合raii的接口(正如我所理解的典型建议)。而不是等待这种情况发生,我试图做一个RAII包装类,其析构函数调用DnsRecordListFree()
和操作符重载强制转换,以获得原始指针。
但是我对如何适当地使用这个句柄或指针来获得一个输出参数感到困惑。当我研究的时候,我学会了unique_ptr
,我已经学了一点,可以与自定义删除器一起使用。
这是我到目前为止的简单代码。可能有比这更多的错误,但我想我可以声明另一个PDNS_RECORD *presult
,并使用它作为输出参数,然后复制或移动或以其他方式将其值分配到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 Worldn";
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 << "Donen";
getchar();
return 0;
}
谢谢!
您可以花一整天的时间尝试适应标准的智能指针,或者您可以自己编写。这并不难做到,特别是如果你愿意欺骗并允许访问原始指针本身。
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))
// ...
除非我错过了什么(我没有一个Windows盒子方便编译这个,所以原谅我,如果我是)你的代码是不正确的。就我个人而言,我不会用智能指针这样做,因为你基本上使用它是一个自定义的看门人类(你可以写一个很容易)。
无论如何,首先,你的删除器应该是:
auto pdnsDeleter = [&](PDNS_RECORD ptr){ if (ptr) DnsRecordListFree(ptr, DnsFreeRecordList); };
接下来,你的智能指针的类型应该是:
std::unique_ptr<DNS_RECORD, decltype(pdnsDeleter)> results;
最后,我相信你的加载这个智能指针应该在确定函数成功后:
PDNS_RECORD pdnsrec;
if (DnsQuery(L"google.com", DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pdnsrec, NULL))
{
results.reset(pdnsrec);
}
如果我得到的是正确的,你的删除将被正确地触发的范围退出在获取链。但是,对于您可以使用自己的janitor类有效地简化的工作来说,这似乎工作量太大了。
- IN, OUT, INOUT Parameters
- 即使使用调试编译标志,表达式也是"optimized out"
- C++双重释放或损坏(out)
- 将 out/in out 参数与 if/switch 的 init 语句一起使用
- 在命令行上将输入显示到数组中时如何删除 ./a.out?
- 为什么我的向量::擦除调用会抛出"vector subscript out of range"?
- 解决方案在第 25 行执行错误'out of bounds'
- C++ 向量加减抛出"expression: vector subscript out of range."错误
- 对函数的 out 字符串参数使用 swap 与赋值
- 运行编译的 a.out 后出现分段错误(核心转储)错误
- 在 Metal 着色器代码中,如何定义函数的 in/out 参数变量?
- 赋值运算符上的双重释放或损坏(out)
- "in"和"out"在参数方向上是什么意思?
- 从 MSVC14 切换到 MSVC16 会导致"compiler is out of heap space (C1060)"错误
- -bash:/a.out:无法执行二进制文件:Exec格式错误
- 庞大的初始化列表,如何修复"fatal error C1060: compiler is out of heap space"
- 从 std::ostream 重载 << 运算符时,为什么编译器会给出"too many parameters for this operator function"错误?
- C++ 调用析构函数后动态模板队列"double free or corruption (out)"
- 在 c++ 中,你有像 c# 中那样'out parameters'吗?
- RAII, unique_ptr, and out parameters