【问题标题】:Closure deleter in initializer list (C++0x) and compiler warning初始化列表 (C++0x) 中的闭包删除器和编译器警告
【发布时间】:2011-06-15 02:53:54
【问题描述】:

我从 Visual C++ 2010 中获得了 warning C4355: 'this' : used in base member initializer list

我有一个持有句柄的类,我想自动关闭句柄即使该类的 ctor 失败(因此不调用它的 dtor)。但是,我不想费心制作一个完整的句柄包装类,而宁愿将它保存在一个智能指针中。所以我写了这个:

foo.h
~~~~~
class Foo
{
    ...
    Log &_log;
    std::unique_ptr<void, std::function<void (void *)>> _handle;
    ...
}

foo.cpp
~~~~~~~
#include <windows.h>
Foo::Foo(Log &lg, ...) : _log(lg), ... _handle(nullptr, [&](void *h){ if (h) { if (!CloseHandle(h)) LOG(_log, "Could not close port: " << LastWinErr()); h = nullptr; } })
{
    HANDLE h(CreateFile( ...
    if (h == ...
    _handle.reset(h);
    ... // Bunch of other stuff that could potentially throw
}

在关闭之前,我用_handle(nullptr, bind(PortDeleter, placeholders::_1, ref(_log))) 之类的东西初始化_handle,但这需要单独定义。

我的问题:警告是否与此特定实例有关?无论哪种方式,详细原因是什么?有什么简单的方法可以避免吗?

【问题讨论】:

  • 您的 lambda 是否必须捕获所有内容 ([&amp;])?如果你只是让它[](或[&amp;_log])会发生什么?
  • 还是同样的问题,因为_log真的是this->_log。 [&lg] 虽然有效。
  • 哦,当然——没有this,您无法访问_log,但您可以访问lg。对不起!

标签: c++11 closures shared-ptr unique-ptr initializer-list


【解决方案1】:

简而言之,如果您传递 this 指针,它会用于访问初始化列表或析构函数中的成员函数或变量,Bad Things Happen™。如果您知道这不会发生,请随意忽略警告。当然,这也是一个很好的警告——如果您在析构函数中访问的任何函数或变量属于该类,那么这是不安全的,因为您可能在它们构造之前/销毁之后访问它们。如果你知道你的初始化/销毁命令,这个问题并不严重,但通常是一个糟糕的举动,因为这使得维护充其量是相当繁琐的。因为您可以改为捕获构造函数参数,所以我不得不推荐它。

【讨论】:

  • 感谢 DeadMG,[&lg] 工作。只是出于好奇,在这种情况下捕获的参数是如何存储的?它是否在与智能指针关联的内存中?似乎在 Foo 对象的生命周期中,会有两个 lg 副本。
  • 我想这就像如果你写struct Foo { int &amp; a; Foo(int &amp; a) : a(a) { } };,引用将存储在函数对象的某个地方。最好不要在原始对象超出范围后使用它!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-15
  • 1970-01-01
  • 2016-08-12
  • 2016-04-26
  • 1970-01-01
  • 1970-01-01
  • 2010-09-28
相关资源
最近更新 更多