アプリ版:「スタンプのみでお礼する」機能のリリースについて

C++の
delete[]と、delete演算子の明確な違いとその使い分けについて

型* ptr = new 型[要素数];
でnewしたものについては、
delete[] ptr;
にて、開放
型* ptr = new 型();
でnewしたものは、
delete ptr;
するものだと、覚えてました、
特に深くは考えていなかったのですが。
std::auto_ptr<T>
では、内部的には、delete[]ではなく
deleteをしているという文章を見ました。

{
std::autoptr<型A> iptr;
iptr = new 型A;


}
のようなときは
いいのですが・・・


{
std::auto_ptr<char> cptr;
cptr = new char[n+1];


}
のようなときは、
動的配列なので、内部的に
delete ptr;
になってしまいます。


このように、テンプレートクラスを自作するときに
実際の特殊な型が決定されるまで、
deleteで、いくのかdelete[]でいくのか決定できないのはつらそうです。

そこで、deleteと、delete[]の正しい意味を
知りたいのですが。

Javaや、.NETには、配列オブジェクトというものが
あります。
C++で、
new char[n+1];
は配列オブジェクトでしょうか?

だとすると、delete[]は
右に来たものが配列オブジェクトなら、
Lengthを(こんなものがあるとして)調べて
1つづつ、まわして、deleteのほうを使ってひとつひとつ開放していく。

右に来たものが配列オブジェクトでなければ
deleteと同じ振る舞いをする。

という動きが物理的に考えれそうで。

delete[]と書いておけば、状況に応じて、
動的配列なら全要素サーチして、開放そうでなければ
deleteという風に、勝手に自動でそうしてくれるなら、
どんなときでも、delete[]にするようにコードを書いておけばよさそうです。。

実際のところどうなんでしょうか?

deleteと、delete[]の明確な意味の違いと、
使用方法の違いについて教えてください。

A 回答 (3件)

> new char[n+1];


> は配列オブジェクトでしょうか?

NO.

delete も delete[] もメモリの解放という意味では同じです。
確保された領域を一気に解放します(部分的に解放できません)。
# mallocでどれだけ確保してあろうがfreeで解放されるのと同様。

異なるのはデストラクタを1回動かすか、それとも"確保された領域/一つのインスタンスが占める大きさ"回動かすか、の違いとなります。
    • good
    • 0
この回答へのお礼

>異なるのはデストラクタを1回動かすか、それとも"確>保された領域/一つのインスタンスが占める大きさ"回動かすか、の違いとなります。

このくだりを聞くと、
delete[]のいっぽん槍でいけそうに聞こえる。
No2さんは、それはやめたほうがよいと、
記述しています。


いづれにせよ。
単体オブジェクト専用のdeleteを内部でやってますが、コンテナを使えばよさそうなのでそうします。

お礼日時:2006/10/04 23:50

> std::auto_ptr<char> cptr; cptr = new char[n+1];


この例なら、std::string (または std::vectorあたり)が適当では?
new[]は主にC言語との互換用/最適化用のためにあるもので、
動的配列はSTLのコンテナ等を使えばよいもの。auto_ptrは単体オブジェクト専用です。

> deleteで、いくのかdelete[]でいくのか決定できないのはつらそうです。

RAIIとか考慮したC++ソースではdelete/delete[]って自分で呼ぶことはほぼ無いですし、
単複がブレても定義と初期化(new/new[])だけの問題ですから、ここは多分間違えないでしょう。

知らない初心者がハマるとか、うっかり間違え易い点は同意ですが、
自分でdeleteするようなコードは慣れてから書けばよく、
初心者がdelete/delete[]を自分で書くのが間違ってると私は思います。
# 生メモリの操作を素人にSTLより先に教えるのがおかしいと思う。

> は配列オブジェクトでしょうか?

C++に配列というオブジェクトはありません。

> という動きが物理的に考えれそうで。

そうすることもできたでしょうが、自動でこういう動きはしません。

> どんなときでも、delete[]にするようにコードを書いておけばよさそうです。。

言語設計がnew/delete、new[]/delete[]のペア前提なので、
newでは要素数等を保持せずnew[]でのみ保持する実装が可能です。
つまり、現状C++では問題が出る可能性があり、やってはいけません。

少しでも無駄な処理/メモリを削れる設計のためでしょう。(そういう言語です>C++)

> どんなときでも、delete[]にするようにコードを書いておけばよさそうです。。

現行C++でこれを実現したい場合、new T;を使わず常に new T[1];とすることはできます。
# C++ ではnew[]の他に、単体専用に効率のよいnewも用意されていると考えたらどうでしょう。
    • good
    • 1
この回答へのお礼

>この例なら、std::string (または std::vectorあたり)が適当では?

std::auto_ptr<char> cptr;
なんぞ使わず、普通に
std::stringで問題ないですね。


>動的配列はSTLのコンテナ等を使えばよいもの。>auto_ptrは単体オブジェクト専用です。

そうでした。コンテナを使えば単体オブジェクト
専用でも気にする必要もなかったです。


>少しでも無駄な処理/メモリを削れる設計のためでしょう。(そういう言語です>C++)

そういう言語なんですね。


>現行C++でこれを実現したい場合、new T;を使わず常に new T[1];とすることはできます。

なるほど、そこまですることもないですが。
どうしても、deleteとdelete[]の違いのせいで、
テンプレートが作れないで悩むような時が
あったら、その
「new T[1];」も1つの選択肢として覚えておきます。


># C++ ではnew[]の他に、単体専用に効率のよいnewも>用意されていると考えたらどうでしょう。

それでわざわざ、2種類あるんですね。
なんのために、いちいち使い分けてんだろ。
めんどくせーとおもってましたが。
これで納得しました。

お礼日時:2006/10/04 23:41

> new char[n+1];


> は配列オブジェクトでしょうか?

JIS X3014:2003の5.3.4 new式の段落5には、「割付けたオブジェクトが配列の場合」という記述が出てくるので、一応は配列オブジェクトなんだと思います。ただし、Javaや.NETの同名のそれとは別物です。
(C/C++における「オブジェクト」は、概ね「変数」の意味です)

> 右に来たものが配列オブジェクトでなければ
> deleteと同じ振る舞いをする。

これを実現するためには、配列かどうかを調べるためのフラグをどこかに仕込んでおく必要があります。つまり、それだけオーバーヘッドになるわけです。そんな機能が必要なら、そういうスマートポインタを自作した方がいいです。

auto_ptrでは、確かに

template <typename T> class auto_ptr<T[]>;

というのを特殊化してやれば、(delete式に関しては)配列も扱えそうな気がしますが、添え字演算子の多重定義をするかどうかなど、セマンティクスが変わるので、あまり有益ではありませんね。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!