0

Any ideas why the following code segfaults?

class foo represents any class. This seams like a good idea for providing an evented interface.

#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();
}
4

4 回答 4

6

It segfauls because foobar is not pointing to anything, you should use foo foobar;.

EDIT:

A short review.

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();
}

e.g.

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();
}
于 2012-12-26T10:59:41.420 回答
3

You never create a foo, you just declare a pointer to it. Change foo* foobar to foo foobar and then get the address to it with &. (Not that you need it in this example).

This should work I guess.

foo foobar;
foobar.bar([](foo* self){return self->val;});
std::cout << foobar._bar() << std::endl;
return 0;
于 2012-12-26T11:00:16.627 回答
2

Because you declared a foobar pointer but didn't use new to allocate memory for it. foo *foobar = new foo(); should make your code work. But you also use automatic storage duration and pass parameter to lambada by reference:

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

  std::cout << foobar._bar();
}
于 2012-12-26T10:59:23.153 回答
1

由于似乎没有人明确表示:您的问题与 lambda 无关;对于普通的功能对象或立即的函数调用,您将遇到完全相同的问题。在担心 lambda 和其他“高级”功能之前,您必须学习该语言的基础知识。在这种情况下:

  1. 您永远不能使用未初始化的变量。使用指针这样做的结果通常比使用 uninitialized 时更引人注目int,但在所有情况下它都是未定义的行为。如果变量具有类类型,则为其定义构造函数,初始化所有成员(和基类)。如果变量没有类类型(并且指针没有类型),请不要在没有初始化子句的情况下定义它。

  2. C++ 默认使用值语义。除非有充分的理由,否则不应使用指针。使用一个值。

在您可以编写尊重这些原则的代码而不使用bindand之前lambda,您不应该查看bindand lambda。在你知道如何走路之前,你不能跑步。

于 2012-12-26T11:41:37.993 回答