std::thread
コンストラクターの仕様によると
効果:スレッド型のオブジェクトを構築します。新しい実行スレッドはINVOKEDECAY_COPYDECAY_COPYを実行し 、DECAY_COPY(
へ の呼び出しは構築スレッドで評価されます。( std::forward<F>(f)),
(std::forward<Args>(args))...)
ここで、DECAY_COPY(x)decay_copy(x)
は、次のように定義されている場所を呼び出すことを意味します。
template <class T> typename decay<T>::type decay_copy(T&& v)
{ return std::forward<T>(v); }
これが意味するのは、引数が「減衰」してコピーされるということです。つまり、引数は値によって転送され、cv資格を失います。スレッドによって実行されるターゲット関数は参照によってそのパラメーターを取得しようとしているため、参照が値によって渡されたオブジェクトにバインドできないというコンパイラエラーが発生します。
これは仕様によるものであり、デフォルトでは、std::thread
getに渡されるローカル変数は参照ではなく値によって渡されます(つまり、コピーされます)。これにより、新しいスレッドには、スコープ外のローカル変数へのぶら下がり参照がなくなり、未定義の動作が発生します。
reference_wrapper
参照によって変数を渡すことが安全であることがわかっている場合は、「減衰」セマンティクスの影響を受けず、ターゲットオブジェクトを参照して変数を転送するを使用して、明示的に渡す必要があります。reference_wrapper
を使用して作成できますstd::ref
。