【问题标题】:valid variable capture from lambda来自 lambda 的有效变量捕获
【发布时间】:2011-12-11 02:04:27
【问题描述】:

我想知道以下引用捕获样式是否有效:

struct Foo {
 Foo( boost::function<void()> v);

 int get() const;
};

int main() {
 Foo instance( [&]() -> void { int value = instance.get(); .... } );

如您所见,我正在捕获对传递 lambda 时正在构造的对象的引用。看起来,如果在构造函数完全执行之前调用 lambda,那么您正在访问一个部分构造的对象,并且您会遇到所代表的所有危险。

但是,这是否允许?似乎只要您确保了解何时可以调用 lambda 就可以了

【问题讨论】:

  • Foo的构造函数对v做了什么?
  • 它可能会存储它以供以后调用。估计是在施工之后。据了解,在完全构建之前调用它会是一个错误,或者至少是有风险的
  • 它只是从最新的 MSVC 和英特尔 C++ 编译器中得到一个编译错误:“instance 未定义”。所以,答案很明确:这是不允许的。或者,您可以在 lambda 中将 Foo* 作为参数传递,并在调用 lambda 时传递 this
  • @minjang:它在我的 gcc 4.5.2 上编译得很好,std::function
  • 我很确定 gcc 是错误的,它不应该编译。变量的作用域直到声明之后才开始。

标签: c++ lambda pass-by-reference c++11


【解决方案1】:

在您通过在 Foo 构造函数中写入 v() 来执行 lambda 之前,它不会执行。如果你这样做,那么就像你直接从构造函数调用函数get()一样,这没关系,如果 get不是virtual函数并且你已经实现了get 也可以从构造函数中调用它。例如,如果你这样做:

在此,get 的实现不需要完全构造对象。

另外,虽然它与您的问题无关,但仍然请注意,由于您使用的是 C++11(正如 lambda 的使用所暗示的那样),为什么不使用 std::function 而不是 @ 987654331@(就像我在demo 中所做的那样)?如果你的编译器支持 lambda,它也会支持std::function,因为它的实现非常简单。

【讨论】:

    【解决方案2】:

    如果 lambda 函数对象被存储并且直到对象完全构造后才被调用,那么就没有问题。与 C++ 中的其他地方一样,可以编写具有未定义行为的代码,以便更方便地利用已定义行为的子集。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-26
      • 2011-11-05
      • 1970-01-01
      • 1970-01-01
      • 2018-06-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多