名前空間
変種
操作

コピーコンストラクタ

提供: cppreference.com
< cpp‎ | language
 
 
C++言語
一般的なトピック
フロー制御
条件付き実行文
繰り返し文 (ループ)
ジャンプ文
関数
関数宣言
ラムダ関数宣言
inline 指定子
例外指定 (C++20未満)
noexcept 指定子 (C++11)
例外
名前空間
指定子
decltype (C++11)
auto (C++11)
alignas (C++11)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点
文字 - 文字列 - nullptr (C++11)
ユーザ定義 (C++11)
ユーティリティ
属性 (C++11)
typedef 宣言
型エイリアス宣言 (C++11)
キャスト
暗黙の変換 - 明示的な変換
static_cast - dynamic_cast
const_cast - reinterpret_cast
メモリ確保
クラス
クラス固有の関数特性
特別なメンバ関数
テンプレート
その他
 
 

クラス T のコピーコンストラクタは、第1引数が T&const T&volatile T& または const volatile T& であって、他の引数がないか残りの引数すべてがデフォルト値を持つ、非テンプレートコンストラクタです。

目次

[編集] 構文

class_name ( const class_name & ) (1)
class_name ( const class_name & ) = default; (2)
class_name ( const class_name & ) = delete; (3)

ただし class_name は現在のクラス (またはクラステンプレートの現在の実体化) を表さなければなりません。 または、名前空間スコープまたはフレンド宣言で宣言されたときは、修飾されたクラス名でなければなりません。

[編集] 説明

  1. コピーコンストラクタの一般的な宣言。
  2. コピーコンストラクタを強制的にコンパイラに生成させます。
  3. コピーコンストラクタの暗黙の生成を回避します。

コピーコンストラクタは、オブジェクトが同じ型の別のオブジェクトから (直接初期化またはコピー初期化によって) 初期化されるときに呼ばれます (オーバーロード解決がより良いマッチを選択した場合または呼び出しが省略された場合は除きます)。 これには以下が含まれます。

  • 初期化。 T a = b; または T a(b);、ただし b は T 型です。
  • 関数の引数渡し。 f(a);、ただし aT 型で fvoid f(T t) です。
  • 関数の戻り。 T f() のような関数の内部における return a;、ただし aT 型であり、 Tムーブコンストラクタを持たない。


[編集] 暗黙に宣言されたコピーコンストラクタ

クラス型 (structclass または union) に対してユーザ定義されたコピーコンストラクタが提供されない場合、コンパイラは常にコピーコンストラクタをそのクラスの非 explicit かつ inline public なメンバとして宣言します。 この暗黙に宣言されたコピーコンストラクタは、以下のすべてが真の場合、 T::T(const T&) の形式を持ちます。

  • T の直接および仮想の基底 B のそれぞれが const B& または const volatile B& を引数とするコピーコンストラクタを持つ。
  • クラス型またはクラスの配列型の T の非静的データメンバ M のそれぞれが const M& または const volatile M& を引数とするコピーコンストラクタを持つ。

そうでなければ、暗黙に宣言されたコピーコンストラクタは T::T(T&) です (これらのルールにより、暗黙に宣言されたコピーコンストラクタは volatile な左辺値引数を束縛できません)。

クラスは複数のコピーコンストラクタ、例えば T::T(const T&)T::T(T&) の両方を持つことができます。 何らかのユーザ定義コピーコンストラクタが存在する場合でも、ユーザはキーワード default を用いて、暗黙に宣言されたコピーコンストラクタの生成を強制できます。

(C++11以上)

暗黙に宣言された (または最初の宣言においてデフォルト化された) コピーコンストラクタは、動的例外指定 (C++17未満)例外指定 (C++17以上)で説明されている通りの例外指定持ちます。

[編集] 削除された暗黙に宣言されたコピーコンストラクタ

以下の条件のいずれかが真の場合、クラス T に対する暗黙に宣言されたコピーコンストラクタは、未定義です。 (C++11未満)
以下の条件のいずれかが真の場合、クラス T に対する暗黙に宣言されたまたはデフォルト化されたコピーコンストラクタは、削除されたものとして定義されます。 (C++11以上)
  • T がコピーできない (削除された、アクセス不可能な、または曖昧なコピーコンストラクタを持つ) 非静的データメンバを持つ。
  • T がコピーできない (削除された、アクセス不可能な、または曖昧なコピーコンストラクタを持つ) 直接または仮想の基底クラスを持つ。
  • T が削除されたまたはアクセス不可能なデストラクタを持つ直接または仮想の基底クラスを持つ。
  • T が union ライクなクラスであり、非トリビアルなコピーコンストラクタを持つ変種メンバを持つ。
  • T が右辺値参照型のデータメンバを持つ。
  • T がユーザ定義ムーブコンストラクタまたはムーブ代入演算子を持つ (この条件は暗黙に宣言された (デフォルト化されたではない) コピーコンストラクタを削除させるだけです)。
(C++11以上)

[編集] トリビアルなコピーコンストラクタ

以下の条件がすべて真の場合、クラス T に対するコピーコンストラクタはトリビアルです。

  • ユーザ定義されていない (つまり、暗黙に定義またはデフォルト化されていない)。 また、デフォルト化されている場合は、そのシグネチャが暗黙に定義された場合と同じである)。 (C++14未満)
  • T が仮想メンバ関数を持たない。
  • T が仮想基底クラスを持たない。
  • T のすべての直接の基底について、選択されたコピーコンストラクタがトリビアルである。
  • T のすべてのクラス型 (またはクラスの配列型) の非静的メンバについて、選択されたコピーコンストラクタがトリビアルである。

非 union クラスに対するトリビアルなコピーコンストラクタは、実質的に引数のすべてのスカラーな部分オブジェクト (およびその部分オブジェクトの部分オブジェクトの…を再帰的に含みます) をコピーし、それ以外の処理を行いません。 しかし、パディングバイトはコピーされる必要はなく、値が同じである限り、コピーされた部分オブジェクトのオブジェクト表現が同じである必要さえもありません。

TriviallyCopyable なオブジェクトは、そのオブジェクト表現を手動で (例えば std::memmove で) コピーすることによってコピーできます。 C 言語と互換性のあるすべてのデータ型 (POD 型) はトリビアルにコピー可能です。

[編集] 暗黙に定義されたコピーコンストラクタ

暗黙に宣言されたコピーコンストラクタが削除されない場合は、 ODR 使用された場合、コンパイラによって定義されます (つまり、関数の本体が生成され、コンパイルされます)。 union 型の場合、暗黙に定義されたコピーコンストラクタは (std::memmove によって行われたかのように) そのオブジェクト表現をコピーします。 非 union クラス型 (class および struct) の場合、暗黙に定義されたコピーコンストラクタはそのオブジェクトの基底と非静的メンバの完全なメンバ単位のコピーを、その初期化の順序で、直接初期化を用いて行います。 これが constexpr コンストラクタの要件を満たす場合、生成されるコピーコンストラクタは constexpr です。 (C++11以上)

T がユーザ定義デストラクタまたはユーザ定義コピー代入演算子を持つ場合、暗黙に定義されたコピーコンストラクタの生成は非推奨です。

(C++11以上)

[編集] ノート

多くの状況で、たとえ可視な副作用を持つ場合でも、コピーコンストラクタは最適化によって除去されます。 コピー省略を参照してください。

[編集]

struct A
{
    int n;
    A(int n = 1) : n(n) { }
    A(const A& a) : n(a.n) { } // ユーザ定義のコピコン
};
 
struct B : A
{
    // 暗黙のデフォコン B::B()
    // 暗黙のコピコン B::B(const B&)
};
 
struct C : B
{
     C() : B() { }
 private:
     C(const C&); // コピー禁止 (C++98 スタイル)
};
 
int main()
{
    A a1(7);
    A a2(a1); // コピコンを呼びます
    B b;
    B b2 = b;
    A a3 = b; // A& への変換 + コピコン
    volatile A va(10);
    // A a4 = va; // コンパイルエラー
 
    C c;
    // C c2 = c; // コンパイルエラー
}

[編集] 欠陥報告

以下の動作変更欠陥報告は以前に発行された C++ 標準に遡って適用されました。

DR 適用先 発行時の動作 正しい動作
CWG 2171 C++14 X(X&) = default was non-trivial made trivial
CWG 496 C++11 structs with volatile members were trivially copyable volatile members make copy non-trivial
CWG 2094 C++14 volatile members make copy non-trivial structs with volatile members are trivially copyable