constへのポインターの削除(T const *)


89

constポインタに関する基本的な質問があります。constポインターを使用して非constメンバー関数を呼び出すことは許可されていません。ただし、constポインターでこれを行うことは許可されています。

delete p;

これは、本質的に非const 'メソッド'であるクラスのデストラクタを呼び出します。なぜこれが許可されるのですか?これをサポートするだけですか?

delete this;

それとも他の理由がありますか?

回答:


112

サポートすることです:

// dynamically create object that cannot be changed
const Foo * f = new Foo;

// use const member functions here

// delete it
delete f;

ただし、問題は動的に作成されたオブジェクトに限定されないことに注意してください。

{
 const Foo f;
 // use it
} // destructor called here

constオブジェクトでデストラクタを呼び出すことができなかった場合、constオブジェクトをまったく使用できませんでした。


21
最新の編集には+1。これが本当の理由だと思います。constオブジェクトの自動デストラクタ呼び出し-deletefとほぼ同じです。ここで、f-const上のポインター。
bayda 2009

const Foo * fまたはFoo const * fFooへのconstポインタではありません。Fooをconstするのはpoinerです。Foo * const f Fooへのconstポインタです。
user113736 9319年

48

このように言えば、許可されていない場合、const_castを使用せずにconstオブジェクトを削除する方法はありません。

意味的には、constは、オブジェクトが不変でなければならないことを示します。ただし、これはオブジェクトを削除してはならないことを意味するものではありません。


3
デストラクタはかなり暴力的な方法でオブジェクトを変更できるため、これは私が以前は気付いていなかった「不変」という単語の奇妙な使用法であるに違いありません...
DarthGizka 2016年

1
@DarthGizkaいいえ、デストラクタはオブジェクトがある状態からない状態にあなたを連れて行きます。C ++は、破壊後の「突然変異」を観察する方法を定義していません
Caleth 2018

@ Caleth:標準では、デストラクタが完了した後にオブジェクトを表示できない場合がありますが、破壊によって引き起こされる副作用を確認することは確かに許可されています。したがって、「不変」オブジェクトの突然変異を観察可能にするために、状況を簡単に調整できます。米国では、死体がない場合、殺人を起訴することは困難ですが、それでも殺人です(そして有罪判決に十分な他の証拠があるかもしれません)。同じ違い。
DarthGizka 2018

6

constポインターを使用してconst以外のメンバー関数を呼び出すことは許可されていません。

はい、そうです。

class Foo
{
public:
  void aNonConstMemberFunction();
};

Foo* const aConstPointer = new Foo;
aConstPointer->aNonConstMemberFunction(); // legal

const Foo* aPointerToConst = new Foo;
aPointerToConst->aNonConstMemberFunction(); // illegal

非constオブジェクトへのconstポインターと、constオブジェクトへの非constポインターを混同しました。

そうは言っても、

delete aConstPointer; // legal
delete aPointerToConst; // legal

ここで他の回答ですでに述べられている理由から、どちらかを削除することは合法です。


5

コンストラクタとデストラクタは「メソッド」と見なされるべきではありません。これらは、クラスのオブジェクトを初期化および破棄するための特別な構造です。

「constpointer」は、オブジェクトが生きている間に操作が実行されても、オブジェクトの状態が変更されないことを示します。


5

別の見方をすると、constポインターの正確な意味は、そのオブジェクトや他のポインター、または同じオブジェクトへの参照を介して表示される、ポイントされたオブジェクトに変更を加えることができないということです。ただし、オブジェクトが破壊されると、以前に削除されたオブジェクト占めていたアドレスへの他のすべてのポインタは、そのオブジェクトへのポインタではなくなります。それらは同じアドレスを格納しますが、そのアドレスはもはやどのオブジェクトのアドレスでもありません(実際、すぐに別のオブジェクトのアドレスとして再利用される可能性があります)。

この区別は、C ++のポインターが弱参照のように動作する場合、つまりオブジェクトが破棄されるとすぐに、オブジェクトへのすべての既存のポインターがすぐに 0。(これは、実行時にコストがかかりすぎてすべてのC ++プログラムに課すことができないと考えられる種類のことであり、実際、完全に信頼できるものにすることは不可能です。)

更新:9年後にこれを読み返すと、それは弁護士っぽいです。私は今あなたの最初の反応が理解できると思います。突然変異を禁止するが破壊を許可することは明らかに問題があります。constポインター/参照の暗黙の契約は、それらの存在がターゲットオブジェクトの破壊(別名自動ガベージコレクション)のブロックとして機能することです。

これに対する通常の解決策は、代わりに他のほとんどすべての言語を使用することです。


constへのポインターが指すものを破壊できない場合、そのstd::unique_ptr<const T>人生の終わりにどのように対処しますか?
カレス2018

@Calethの場合、C ++ではそれに対する解決策はありません。これは一般的な問題の一例にすぎません。C++では、const修飾子は、「ターゲットを完全に破壊し、他のすべての参照を無効にし、未定義の動作の原因にすることができる場合を除いて、ターゲットを変更することはできません」を意味します。だからこそ、この種の質問は他の言語を検討するきっかけとなるはずだと思います。そこにはUBの穴があり、別の基本的なアプローチをとらなければ解決できません。
Daniel Earwicker 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.