最終更新日時(UTC): 2025年07月08日 15時33分39秒
Akira Takahashi が更新

履歴 編集

function
<memory>

# std::unique_ptr::operator=(C++11)

    unique_ptr& operator=(unique_ptr&& u) noexcept;           // (1) C++11
    constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; // (1) C++23

    template <class U, class E>
    unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;           // (2) C++11 単一オブジェクト版
                                                                    // (2) C++17 配列版
    template <class U, class E>
    constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept; // (2) C++23

    unique_ptr& operator=(nullptr_t) noexcept;            // (3) C++11
    constexpr unique_ptr& operator=(nullptr_t) noexcept;  // (3) C++23

    unique_ptr& operator=(const unique_ptr&) = delete;    // (4) C++11

## 概要

- (1) : 自身が保持しているリソースを解放し、`u`から`*this`に所有権を譲渡する。
- (2) : 自身が保持しているリソースを解放し、変換可能な`u`から`*this`に所有権を譲渡する
- (3) : 自身が保持しているリソースを解放する。
- (4) : コピー代入禁止。

## 要件

- (1) : デリータの型`D`が、例外を投げずにムーブ構築可能であること。
- (2) 単一オブジェクト : 以下の条件を満たさない場合、この関数はオーバーロード解決の候補から外れる：
  - `unique_ptr<U, E>::pointer`が、`pointer`に暗黙変換可能な型であること。
  - `U`が配列型ではないこと。
  - `is_assignable_v<D&, E&&> == true`であること。
- (2) 配列 : 以下の条件を満たさない場合、この関数はオーバーロード解決の候補から外れる：
  - `U`は配列型であること。
  - `*this`の型`UP`について、`UP::pointer`と`UP::element_type*`が同じ型であること。
  - `u`の型`UP`について、`UP::pointer`と`UP::element_type*`が同じ型であること。
  - `unique_ptr<U, D>::element_type(*)[]`から`unique_ptr<T[], D>::element_type(*)[]`へ変換可能であること。
  - `is_assignable_v<D&, E&&> == true`であること。

## 効果

- (1), (2) :

    reset(u.release());
    d_ = std::forward<E>(u.get_deleter());

- (3) : `reset()`

## 戻り値

`*this`

## 例外

投げない

## 例

    #include <cassert>
    #include <memory>

    int main()
    {
      std::unique_ptr<int> p0(new int(3));

      // (1) ムーブ代入
      // p0の所有権をp1に譲渡する
      std::unique_ptr<int> p1;
      p1 = std::move(p0);
      assert(*p1 == 3);

      // (2) 変換可能な型からの所有権移動
      // p1の所有権をp2に譲渡する
      std::unique_ptr<const int> p2;
      p2 = std::move(p1);
      assert(*static_cast<const int*>(p2.get()) == 3);

      // (3) リソース解放
      std::unique_ptr<int> p3(new int(3));
      p3 = nullptr;
      assert(!p3);
    }

### 出力

## バージョン

### 言語

- C++11

### 処理系

- GCC: 4.4.7 (nullptr_tのオーバーロード以外) ✅, 4.6.4 ✅
- Clang: 3.0 ✅
- ICC: ?
- Visual C++: 2010 ✅, 2012 ✅, 2013 ✅
  - 2010にはnullptr_tのオーバーロードがない。
  - 2012までは、delete宣言に対応していないため、代わりにprivateで宣言のみ行う手法で代用されている。

## 参照

- LWG Issue 2047. Incorrect "mixed" move-assignment semantics of `unique_ptr`
- LWG 2246. `unique_ptr` assignment effects w.r.t. deleter
- LWG 2228: Missing SFINAE rule in unique_ptr templated assignment
  - (2)のSFINAEルール不足の欠陥修正の提案文書
- P2273R3 Making `std::unique_ptr` constexpr