[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
質問
C++11のルールでは、6つのもの(デフォルトコンストラクタ、コピーコンストラクタ、移動コンストラクタ、コピー代入、移動代入、デストラクタ)がデフォルトで生成されることになっています。2番目の規則では、カスタムコピー、移動、デストラクタが定義されると、これらのデフォルトの操作は生成されません。 しかし、以下の私のコードでは、そのようなことはありません。しかし、このコードではコンパイルに失敗し、次のようなエラーが発生します。
call to implicitly deleted copy constructor of 'Uni'
Uni用のコピーコンストラクタを自作すると、すべてがうまくいきます。(参考までにコードにコメントをつけてあります)
何かご意見がありましたら、よろしくお願いします。
最後に、私はこれをMac、Xcode、LLVMコンパイラで実行しています。
ありがとうございました。
#include <iostream>
class A
{
public:
A(int i) :num{i}
{
std::clog<< "ctor A() num = " << num << "\n";
}
A( A const &aRef)
:num{aRef.num}
{
std::clog << " copy ctor A( A const &aRef) num = " << num << "\n";
}
int value()
{
return num;
}
private:
int num;
};
class Uni
{
public:
Uni(A* aptr) : up{aptr}
{
std::clog << " ctor Uni value = " << up.get()->value() << "\n";
}
/*Uni(Uni const &uRef)
{
std::clog << " copy ctor Uni copying obj pointed by unique_ptr\n";
up.reset(uRef.up.get() ? new A{*uRef.up.get()} : nullptr);
}*/
private:
std::unique_ptr<A> up;
};
int main(int argc, const char * argv[])
{
Uni one{new A{10}};
Uni two{one}; //default copy ctor is implicitly deleted. why ?
}
解決方法は?
C++11の特殊メンバの自動生成ルールは、投稿されたような単純なものではありません。最も重要な違いは、メンバが暗黙的に宣言されていても、削除済みとして定義されているケースがあることです。あなたの場合はそうなっているのです。
C++11、[class.copy]§11。
クラスのデフォルトのコピー/移動コンストラクタ
X
が削除されたと定義されます (8.4.3)。X
があります。
- 対応する自明でないコンストラクタを持つバリアントメンバと
X
はユニオンのようなクラスです。- クラスタイプの非静的データメンバである
M
(またはその配列) に適用される過負荷解消 (13.3) のため、コピー/移動ができない。M
の対応するコンストラクタがあいまいであったり、削除された関数やデフォルトのコンストラクタからアクセスできない関数であったりする場合です。- 直接または仮想基底クラス
B
に適用される過負荷の解決 (13.3) のためにコピー/移動できないものです。B
の対応するコンストラクタがあいまいであったり、削除された関数やデフォルトのコンストラクタからアクセスできない関数であったりする場合です。- デフォルトのコンストラクタから削除されるかアクセスできないデストラクタを持つ型の、直接または仮想の基底クラスまたは非静的データメンバ。
- コピーコンストラクタの場合、rvalue参照型の非静的データメンバ、または
- 移動コンストラクタの場合、非静的データメンバ、移動コンストラクタを持たない直接ベースクラスまたは仮想ベースクラスで、三重にコピー可能ではない型。
(強調)
より一般的には、自動生成されるクラスメンバに関するルールがあります。
-
クラスにユーザーが提供するコンストラクタがない場合、デフォルトのコンストラクタが宣言されます。
-
クラスがユーザー提供のコピーコンストラクタを持っていない場合、1 つが宣言されます。
-
クラスが { ユーザ提供のコピーまたは移動コンストラクタ、ユーザ提供のコピーまたは移動代入演算子、ユーザ提供のデストラクタ } のいずれも持たない場合、移動コンストラクタが宣言されます(ただし、以下の (*) を参照してください)。
-
クラスがユーザー提供のコピー代入演算子を持たない場合、その演算子が宣言されます。
-
クラスが { ユーザ提供のコピーまたは移動コンストラクタ、ユーザ提供のコピーまたは移動代入演算子、ユーザ提供のデストラクタ } のいずれも持たない場合、移動代入演算子が宣言されます(ただし、以下の (*) を参照してください)。
-
クラスがユーザー提供のデストラクタを持たない場合、デストラクタが宣言されます。
自動的に宣言されたメンバーは、defaulted(デフォルトの動作をする)として定義するか、deleted(使おうとするとエラーが発生する)として定義することができます。経験則では、"defaultedのバージョンが意味を持つ場合、defaultedとして定義されます。そうでなければ、deletedとして定義されます。
この文脈では、quot;makes sense" とは、削除された、あいまいな、アクセスできない、またはその他の不正な関数を呼び出そうとしないことを意味します(" 例えば、この回答の最初の部分で引用した標準のビットでは、コピーコンストラクタについて何が "make sense" でないかをリストアップしています。
さらに、自動的に宣言されたコピー・コンストラクタまたはコピー代入演算子は、クラスがユーザー提供の移動コンストラクタまたは移動代入演算子を持つ場合、削除されたものとして定義されます。
(*) 自動宣言された移動コンストラクタや移動代入演算子が削除と定義される場合、代わりに全く宣言されません。このルールは、そのようなクラスを移動しようとしたときに、エラーを発生させることなく、暗黙のうちにコピーに戻るようにするために存在します。
関連
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み】C++の余分な資格エラー
-
[解決済み】1つ以上の多重定義されたシンボルが見つかる
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み] C++で、あるコンストラクタを別のコンストラクタから呼び出す(コンストラクタ・チェイニングを行う)ことは可能ですか?
-
[解決済み] コピーアンドスワップ慣用句とは?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み】IntelliSense:オブジェクトに、メンバー関数と互換性のない型修飾子がある
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み】変数やフィールドがvoid宣言されている