29

移動できないのはなぜですかstd::lock_guard。コードをより良くすることができます:

auto locked = lock_guard(mutex);

それ以外の

std::lock_guard<std::mutex> locked(mutex);

次のように、独自のバージョンを作成する際に何か問題がありますか?

template <typename T> class lock_guard_
{
  T* Mutex_;
  lock_guard_(const lock_guard_&) = delete;
  lock_guard_& operator=(const lock_guard_&) = delete;
public:
  lock_guard_(T& mutex) : Mutex_(&mutex)
  {
    Mutex_->lock();
  }
  ~lock_guard_()
  {
    if(Mutex_!=nullptr)
      Mutex_->unlock();
  }
  lock_guard_(lock_guard_&& guard)
  {
    Mutex_ = guard.Mutex_;
    guard.Mutex_ = nullptr;
  }
};

template <typename T> lock_guard_<T> lock_guard(T& mutex)
{
  return lock_guard_<T>(mutex);
}

?

移動可能にするのが悪い考えである根本的な理由はありますか?

4

2 に答える 2

13

できるよ:

auto&& g = std::lock_guard<std::mutex> { mutex };

これは控除を実行しないため、明らかにこれは完全に満足できるものではありません。推論ファクトリでの試みは、リストの初期化を使用して移動不可能なオブジェクトを返す必要があるという事実を除けば、ほとんどありません。

template<typename Mutex>
std::lock_guard<Mutex> lock_guard(Mutex& mutex)
{
    mutex.lock();
    return { mutex, std::adopt_lock };
}

を可能にしauto&& g = lock_guard(mutex);ます。

(厄介なダンスstd::adopt_lockは、単項コンストラクタが明示的であるためです。したがって、これはreturn { mutex };許可されていない変換であるため、return std::lock_guard<Mutex> { mutex };実行できませんが、一時的なリストの初期化を実行します — その後、戻り値に移動することはできません.)

于 2014-03-19T11:38:27.497 に答える