0

ラムダ式の変数キャプチャ部分の性質について混乱しています。

void f1();
std::function<int()> f2;

int main() {
    f1();
    std::cout<<f2()<<endl;
}

void f1() {
    int x;
    f2 = [&]() {
        return x;
    };
}

呼び出されるx前に解体されていませんか?f2

4

2 に答える 2

4

はい。未定義の動作を正常に呼び出しました。考えられる結果の 1 つは、x の値を取得することです。もう 1 つは、コンピューターがハード ドライブをフォーマットしたり、プログラムがクラッシュしたり、コンピューターがロボットのパン職人暗殺者に変身してカップケーキを食べさせたりして、セリアック病にかかっていると誤解することです。

これの安全な変形は次のようになります:

int main() {
    f1(7);
    std::cout<<f2()<<endl;
}

void f1(int x) {
    std::shared_ptr<int> spX( new int(x) );
    f2 = [=]() {
        return *spX;
    };
}

また

void f1(int x) {
    f2 = [=]() {
        return x;
    };
}

(int の場合、値で格納しない理由はほとんどありません。より複雑な型の場合は、不必要にコピーすることを避けたい場合があります)。

上記のコメントは、これをより面白い方法で説明していることに注意してください。

現在、一部のコンパイラは、この種の未定義の動作を正確にキャッチするためにスタックをデクリメントするときに、特別な値でスタックにマークを付けます (キャッチとは、プログラマにとってより明確にすることを意味します)。しかし、ほとんどの場合、C++ で未定義の動作を呼び出すことは可能です。

于 2012-10-26T20:16:33.927 に答える
2

x は f2 が呼び出される前に分解されていませんか?

はい、そうです。これは、return xが未定義の動作を引き起こすダングリング参照を評価することを意味します。

この場合、値でキャプチャすることをお勧めします。

f2 = [x]() { return x; }
于 2012-10-26T20:10:09.027 に答える