2017-08-29 4 views
7

私は、次のC++(11)のコードがあります:mutexがまだunlock()からの復帰後に開催された理由を私は理解できない何なぜstd :: unique_lock上でstd :: moveを実行しても効果がありませんか?

#include <mutex> 

void unlock(std::unique_lock<std::mutex> && ulock) 
{ 
} 

int main(void) 
{ 
    std::mutex m; 
    std::unique_lock<std::mutex> ulock(m); 

    unlock(std::move(ulock)); 

    if (ulock.mutex() == &m || ulock.owns_lock()) 
    { 
     throw std::runtime_error(""); 
    } 

    return 0; 
} 

です。私の期待は、std::move()が、unlock()への呼び出しから戻ると、ロックが有効範囲外になり(デストラクタによってロック解除される)ことを期待しています。少なくともstd::move()ulockがミューテックスmから "unbound"になっているはずです。

私には何が欠けていますか?

+7

'std :: move'自体はどこにも移動しません。左辺値を右辺値参照にキャストするだけで、それが移動コンストラクタなどの引数になります。それらは次に、一時的なもの(内部のものと思われるもの)の内部を盗むかもしれません。しかし、あなたのコードはそれらを呼び出すことはありません。 'unlock(std :: move(ulock));'は精巧なノーオペレーションです。 –

+0

'std :: unique_lock'を値で取るように' unlock'を定義し、次にそれに移動して、効果を確認します – WhiZTiM

+3

私はstd :: move()がunique_lockのための移動コンストラクタを呼び出したと仮定していました。そうではないように聞こえます。むしろ、 'unlock()'の右辺値参照は、それが選択すれば(もし意味があれば)moveコンストラクタを使用できるソートの「通知」です。 –

答えて

12
ここ
void unlock(std::unique_lock<std::mutex> && ulock) 

ulock参照です。特別な種類の参照ですが、依然として参照です。これは別のオブジェクトの単なるエイリアスです。その作成には、新しいオブジェクトの作成やあらゆる種類の所有権移転は含まれません。同様に、その存続期間の終わりはデストラクタ呼び出しにつながることはなく、他のオブジェクトを参照するためのエイリアスを失ったことを意味します(機能は終了しているので重要ではありません)。

あなたが所有権を譲渡する場合は、オブジェクトを必要とし、その値ではなく、参照渡し:std::unique_lockがサポートされていないので、

void unlock(std::unique_lock<std::mutex> ulock) 

さて、あなたは、オリジナルのロックをmoveする必要がありますコピーの建設、移動のみ建設。

関連する問題