6

次の関数はスレッドセーフですか? そして、それがスレッドセーフでない場合、その funImpl を非静的にすることで実際にオーバーヘッドがあるのでしょうか? それとも、コンパイラは実際にその関数オブジェクト関数をインライン化し、関数オブジェクトの作成を完全にスキップしますか?

int myfun(std::array<int, 10> values)
{
    static const auto funImpl = [&]() -> int
    {
        int sum = 0;

        for (int i = 0; i < 10; ++i)
        {
            sum += values[i];
        }
        return sum;
    };

    return funImpl();
}

編集:関数シグネチャを次から編集しました:

int myfun(const std::array<int, 10>& values)

に:

int myfun(std::array<int, 10> values)

値のスレッド セーフについて質問しているのではなく、関数ローカル静的変数 funImpl のスレッド セーフについて質問していることは明らかです。

4

1 に答える 1

14

スレッドセーフではないだけでなく、あなたが望むことをしません。

ラムダを静的として定義することにより、最初に呼び出されたときに渡された配列を(参照により)キャプチャします。それ以降の呼び出しは、渡される配列に関係なく、元の配列を参照し続けます。

最初の配列がスコープ外になると、参照がぶら下がっているため、それ以降の呼び出しでUBが呼び出されます。

編集:例http://ideone.com/KCcav

値でキャプチャした場合でも、関数を最初に呼び出したときにのみキャプチャされるため、問題が発生することに注意してください。ダングリングポインタはありませんが、それでもコピーを最初に初期化するだけです。

于 2012-07-23T19:46:04.643 に答える