【问题标题】:Good practice : construction of a complex member from a lambda良好实践:从 lambda 构造复杂成员
【发布时间】:2015-06-08 13:56:17
【问题描述】:

我有时在我的课堂上有这种模式:

class Variant;
struct Foo
{
  int x; 
  int y;
};

struct Bar
{
  int first() const; 
  int second() const; 
};

class Bar
{
  public:
    Bar(Variant v)
    {
       // For brevity there are no 
       // tests in this sample code
       Bar aBar = v.get<Bar>();  // Variant::get is a slow operation
       m_theFoo.x = aBar.first();
       m_theFoo.x = aBar.second();
    }

  private:
    Foo m_theFoo;
};

我宁愿在初始化列表中初始化 m_theFoo。但是,我不想像这样两次调用Variant::get,因为这可能是一个缓慢的操作:

Bar(Variant v):
   m_theFoo{v.get<Bar>().first(), v.get<Bar>().second()}
{
}

所以我想出了这个:

Bar(Variant v):
    m_theFoo{[&] () { 
            Bar aBar = v.get<Bar>();
            return Foo{aBar.first(), aBar.second()};
        }()
    }  
{
}

基本上,初始化是由调用并返回初始化成员的 lambda 完成的。

我想知道这听起来是好还是坏,以及这种初始化方法是否有缺点。例如,lambda 实例化的重量是多少?

把它变成这样的无状态 lambda 会更好吗?

Bar(Variant v):
    m_theFoo{[] (const Variant& v_sub) { 
            Bar aBar = v_sub.get<Bar>();
            return Foo{aBar.first(), aBar.second()};
        }(v)
    }  
{
}

【问题讨论】:

    标签: c++ lambda initialization


    【解决方案1】:

    只需将您的初始化转发给一个函数 - 您可以获得所有好处,而不会让您的代码看起来有点神秘:

    Bar(Variant v)
    : m_theFoo(makeFoo(v))
    { }
    

    与:

    Foo makeFoo(const Variant& v) {
        Bar theBar = v.get<Bar>();
        return Foo{theBar.first(), theBar.second()};
    }
    

    【讨论】:

    • 完全同意这个答案,但只是为了给提问者一些其他好的做法,而我们都在这里:理想情况下 makeFoo 应该只在匿名命名空间内的 .cpp 文件中声明/定义.这可以防止 Bar 的接口以最微小的方式扩展。
    猜你喜欢
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多