質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

3回答

22185閲覧

C++11で、デストラクタ = deleteとする意味について

maisumakun

総合スコア145123

C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

1グッド

5クリップ

投稿2016/05/21 05:26

C++では、仮想関数の宣言に= 0とすることで純粋仮想関数を指定する「純粋指定子」がありましたが、C++11では、

  • デフォルトコンストラクタ・コピーコンストラクタ・代入演算子・デストラクタについて、コンパイラの自動生成したものを使うと明示する= default
  • 特定のメンバ関数がないことを宣言する= delete

のような指定子が加わっています。

そして、この「= delete」で宣言したメンバ関数を呼ぶようなコードを書けば、(呼び出しが明示的か暗黙のうちにかを問わず)コンパイルエラーとなります。代入やインスタンス化など、特定の操作を禁止できるという意味では便利です。

そして、構文上は~someClass() = delete;とできるのですが、以下のような挙動になりました(手元のg++ 4.7.2で-std=gnu++11として動かしてみました)。

  • 宣言自体は問題なく可能
  • そのクラスのローカル変数を宣言しようすると、スコープアウト時の破棄でデストラクタが呼ばれるためコンパイルエラー
  • ポインタを宣言してnewすることは可能(他のメンバ関数も呼べる)
  • ただし、deleteを書くとコンパイルエラー

このような、「newはできるけどdeleteが不可能な上に自動変数にもできない」クラスができあがったのですが、果たして何かに実用できるものなのでしょうか。それとも、じつは「デストラクタを= deleteするのは未定義」なのでしょうか。

raccy👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

デストラクタを呼べない。そのことには理由があります。

「デストラクタを呼ぶべきではない。」これが理由です。

もっとはっきりと書くなら、「自動解放のタイミングでは適切な処理ができない」「引数をつけて呼び出せないデストラクタを利用しての解放を禁止すべきである。」という状況が考えられます。

プログラマに常に明示的解放を要求することは、必要になる場合があります。そのようなときにデストラクタの削除は効果的です。
オブジェクトの初期化・廃棄は、キャストとmalloc、freeと配置new/deleteで可能です。

投稿2016/05/22 10:12

majiponi

総合スコア1720

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんにちは。

MinGW(gcc) 5.2.0では下記だけでもerror: use of deleted function 'Foo::~Foo()'でした。

C++

1struct Foo 2{ 3 ~Foo() = delete; 4}; 5Foo foo;

スタックオーバーフローに幾つかQAがありましたが、スタックに獲得できないようにする効果がある旨しか読み取れませんでした。どんな時便利か、回答している人はいないようなに見えます。(もっと英語力が欲しい。orz)

使える場面としては、インスタンスを作らないクラスしか思いつきません。「このクラスはインスタンスを作るな」とお手軽に明示するために指定するイメージです。正直、使う場面はないような。

n3337の147ページ7.1.6.2 Simple type specifiersの5でデストラクタをdeleteしている、何かのサンプル・コードが記載されているのですが、やはり意味がある使い方には見えませんでした。

C++

1template<class T> struct A { ~A() = delete; }; 2template<class T> auto h() 3-> A<T>; 4template<class T> auto i(T) // identity 5-> T; 6template<class T> auto f(T) // #1 7-> decltype(i(h<T>())); // forces completion of A<T> and implicitly uses 8 // A<T>::˜A() for the temporary introduced by the 9 // use of h(). (A temporary is not introduced 10 // as a result of the use of i().) 11template<class T> auto f(T) // #2 12-> void; 13auto g() -> void { 14f(42); // OK: calls #2. (#1 is not a viable candidate: type 15 // deduction fails (14.8.2) because A<int>::~A() 16 // is implicitly used in its decltype-specifier) 17} 18template<class T> auto q(T) 19-> decltype((h<T>())); // does not force completion of A<T>; A<T>::˜A() is 20 // not implicitly used within the context of this decltype-specifier 21void r() { 22q(42); // Error: deduction against q succeeds, so overload resolution 23 // selects the specialization “q(T) -> decltype((h<T>())) [with T=int]”. 24 // The return type is A<int>, so a temporary is introduced and its 25 // destructor is used, so the program is ill-formed. 26}

投稿2016/05/21 07:32

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2016/05/21 09:11

インスタンス化阻止なら、コンストラクタを=deleteしたほうが確実ですし(むろんnewも不能)…積極的にデストラクタでやる理由もないですよね…
Chironian

2016/05/21 09:27

コンストラクタは3つ(デフォルト、コピー、ムーブ)潰さないといけないので、1つで済むデストラクタはちょっとだけ楽かも。 しかし、意図が分かりにくいし、newはできてしまうし、「積極的にデストラクタでやる理由もない」に賛成です。
guest

0

ローカル変数にできなくなるって面白いですね。

majiponiさんの回答をみて思いついたのはシングルトンオブジェクトの破棄は静的メソッドで行うので、デストラクタはないというようにわかりやすくするとかはあるかもしれないと思いました

投稿2017/06/11 02:54

nullbot

総合スコア910

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問