yohhoyの日記

技術的メモをしていきたい日記

ムーブの跡

C++11におけるムーブされた後のオブジェクト状態についてメモ。

C++11標準規格ではムーブ後のオブジェクト状態について、下記2種類の型に対する要求を規定する。N3264のRationale参照*1

  • [A] 標準ライブラリが提供するクラス
  • [B] 標準ライブラリと組み合わせて利用するユーザ定義クラス*2

[B]ユーザ定義クラス に対しては [A]標準ライブラリ提供クラス に比べて弱い要求条件、つまり標準アルゴリズムが正常動作するために必要最低限の保証しか要求しない*3。ただし [A]標準ライブラリ提供クラス に対する要求はムーブセマンティクスにおける “ベストプラクティス” と捉えることができ、ムーブ操作に対応するユーザ定義クラスでもこのレベルを保証する事が望ましい。

標準ライブラリ提供クラス

標準ライブラリ提供クラスにおいて、ムーブ後のオブジェクトは “有効だが未規定な状態(valid but unspecified state)” となる。

N3337 17.3.26, 17.6.5.15より引用。

valid but unspecified state
an object state that is not specified except that the object's invariants are met and operations on the object behave as specified for its type
[Example: If an object x of type std::vector<int>; is in a valid but unspecified state, x.empty() can be called unconditionally, and x.front() can be called only if x.empty() returns false. -- end example]

Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.

一部の標準ライブラリ提供クラス(テンプレート)では、ムーブ後のオブジェクト状態についてより詳細に規定する。

クラス ムーブ後のオブジェクト状態
unique_ptr ポインタを所有しない(20.7.1/p4, 20.7.1.2.1/p16)
shared_ptr ポインタを所有しない(20.7.2.2/p1, 20.7.2.2.1/p22)
unique_lock Mutexと関連づけられずロック保持しない(30.4.2.2.1/p21)
promise Shared stateを所有しない(30.6.5/p6)
future Shared stateを所有しない(30.6.6/p8)
shared_future Shared stateを所有しない(30.6.7/p10)
packaged_task Shared stateを所有しない(30.6.9.1/p6)

ユーザ定義クラス

標準アルゴリズムと組み合わせるユーザ定義クラスにおいて、ムーブ後のオブジェクト状態は “未規定(unspecified)” を要求する。言い換えると、標準アルゴリズムが求める要件さえ満たしていれば、ユーザ定義クラスにはそれ以上の追加条件が要求されない。

N3337 17.6.3.1のMoveConstructible要件、MoveAssignable要件より該当箇所を引用。rvはムーブ後のオブジェクトを表す。

rv's state is unspecified. [Note: rv must still meet the requirements of the library component that is using it. The operations listed in those requirements must work as specified whether rv has been moved from or not. -- end note]

関連URL

*1:N3264 CH-18 and US-85: Clarifying the state of moved-from objects (Revision 1)

*2:標準ライブラリと組み合わせて利用しないユーザ定義クラスについては、端的にいうとC++11標準では何も要求しない。ムーブ操作はC++の言語仕様ではなくセマンティクスに過ぎないため、標準ライブラリと相互作用しないユーザ定義クラスにどのようなセマンティクスを持たせるかについて、C++標準規格では何ら規定せずプログラマにゆだねている。

*3:例えばMoveConstructible要件のみを要求する標準アルゴリズムと組み合わせるユーザ定義クラスにおいて、ムーブ後のオブジェクトがデストラクトさえ不可能な状態となっても良い。この場合のユーザ定義クラスに対する破棄操作はユーザ側の責任であり、C++標準ライブラリはそこに関与しない。