C++11 Lambda woes

C++11 Lambda woes

本文关键字:woes Lambda C++11      更新时间:2023-10-16

有什么想法为什么以下代码segfaults?

class foo代表任何类。这是提供事件接口的好主意。

#include <iostream>
#include <functional>
class foo
{
public:
  foo()
  {
    val = 42;  
  };
  void bar(std::function<int(foo*)> f)
  {
    this->_bar = std::bind(f, this);
  }
  std::function<int()> _bar;
  int val;
};
int main(void)
{
  foo *foobar;
  foobar->bar([](foo *self)->int{return self->val;});
  std::cout << foobar->_bar();
}

segfauls,因为foobar没有指向任何东西,您应该使用foo foobar;

编辑:

简短的评论。

class foo
{
public:
  foo()
  {
    val = 42;  // Use initialization list.
  };
  void bar(std::function<int(foo*)> f) // Use reference (foo&) instead of pointer (foo*).
  {
    this->_bar = std::bind(f, this); // Move "f" into bind and use "std::ref()" so you can pass "*this" by reference without copying.
  }
  // Hide local member variables
  std::function<int()> _bar; // Never use _ as a prefix, only the compiler is allowed to use _ prefix.
  int val;
};
int main(void)
{
  foo *foobar; // Use value semantics, i.e. "foo foobar".
  foobar->bar([](foo *self)->int{return self->val;});
  std::cout << foobar->_bar();
}

,例如

class foo
{
public:
    foo()
        : val_(42)
    {
    };
    void set_bar(std::function<int(foo&)> f)
    {
        bar_ = std::bind(std::move(f), std::ref(*this));
    }
    int invoke_bar() const
    {   
        return bar_;
    }
    int get_val() const
    {
        return val_;
    }
private:
    std::function<int()> bar_;
    int val_;
};
int main(void)
{
  foo foobar;
  foobar.set_bar([](foo& self) -> int
  {
     return self.get_val();
  });
  std::cout << foobar.invoke_bar();
}

您永远不会创建一个foo,您只需声明指针。将foo* foobar更改为foo foobar,然后使用&获取地址。(不是在此示例中需要它)。

我猜这应该有效。

foo foobar;
foobar.bar([](foo* self){return self->val;});
std::cout << foobar._bar() << std::endl;
return 0;

,因为您声明了foobar指针,但没有使用new为其分配内存。foo *foobar = new foo();应该使您的代码工作。但是您还使用自动存储持续时间,并通过参考将参数传递给Lambada:

int main(void)
{
  foo foobar;
  foobar.bar([](foo *self)->int{return self->val;});
  std::cout << foobar._bar();
}

,因为似乎没有人明确地说:您的问题与Lambda无关;正常功能对象或即时功能调用,您将遇到完全相同的问题。在担心Lambda和其他"高级"功能之前,您必须学习该语言的基础知识。在这种情况下:

  1. 您永远无法使用非初始化的变量。使用指针进行的结果通常比您使用非初始化的int时更为壮观,但在所有情况下,这都是不确定的行为。如果变量具有类类型,则为其定义构造函数,该构造函数初始化所有成员(和基本类)。如果变量没有类类型(并且指针确实没有类型),则切勿在没有初始化条款的情况下定义它。

  2. c 默认使用值语义。除非有充分的理由,否则您应该使用指针。使用值。

直到您可以编写尊重这些原理而无需使用bindlambda的代码,您就不应该查看bindlambda。在知道如何行走之前,您不能跑步。