2017-07-22 10 views
0

サンプル:
#include "stdafx.h" 
#include <functional> 
#include <iostream> 
#include <string> 
std::function<void(int)> Foo() 
{ 
    int v = 1; 
    int r = 2; 
    auto l = [v, r](int i) 
    { 
     std::cout << v << " " << r << " " << i << std::endl; 
    }; 
    return l; 
} 

int main() 
{ 
    auto func = Foo(); 
    func(3); 
    return 0; 
} 

operator()によって呼び出されたときにstd :: functionを返すstd :: functionオブジェクトはどのように機能しますか?

はなぜ func(3)(Fooの中のラムダの仮引数である私に 3を渡すことができます)。私は考えることができません。ありがとう。

+3

ラムダ*を返す* "' std :: function'オブジェクトはありません。 'Foo'はラムダを使って定義した' std :: function'を返します – UnholySheep

+8

'func(3)'は*未定義のビヘイビアーを呼び出す*ラムダキャプチャの '&r'はライフタイムが終了した変数を参照するためです。関数を呼び出す時間(ぶら下がっている参照) – UnholySheep

+2

UBを呼び出すプログラムについて推論しようとするのは無意味です。最初にあなたのUBバグを修正し、*次に*それについて推論しよう。 –

答えて

1

TL; DR:引数3を関数Fooに渡さないでください。 オブジェクトfuncに渡します。

もう少し詳しく説明します。


まず第一に、私はラムダが何であるかを明確にしたいと思います。 A C++のlambdaは、匿名のファンクタクラスに過ぎません。したがって、本質的に文法的な砂糖です。 クロージャはラムダ型のインスタンスです。しかし、かなり頻繁に "ラムダ"と "クロージャー"という言葉は同じ意味で使われています。

だからあなたの関数内でFoo()あなたは閉鎖オブジェクトこのコードに技術的に相当しますl

auto l = [v, r](int i) 
{ 
    std::cout << v << " " << r << " " << i << std::endl; 
}; 

作成:

struct Functor 
{ 
    Functor(int v, int r) : v_(v), r_(r) {} 

    void operator()(int i) const { 
     std::cout << v_ << " " << r_ << " " << i << std::endl; 
    } 

private: 
    int v_; 
    int r_; 
}; 
Functor l(v, r); 

を、次の行にあなたはSTDを返します:: functionオブジェクトです。

return l; // actually creates std::function<void(int)>(l) and returns it 

だから自分のmain関数でfuncコピーFoo()に通話中に得られた値v, rを格納し、上記構造体と同様operator()を定義するだけオブジェクトあります。 したがって、func(3)を呼び出すと、実際のオブジェクトfuncでオブジェクトメソッドが呼び出され、構文的な砂糖なしではfunc.operator()(3)のように見えます。

ここには私の要点を示すためにlive exampleがあります。

あなたの混乱を解決するのに役立つことを望みます。

+0

thx、私はコードがstd ::関数を返すことに気付かず、C++の抽象的な魔法と見なします。 'Foo'は単なるtrival関数です。 – czxyl

関連する問題