2012-02-13 17 views
3

これまではJavaでプログラムを書いてきました。だから、私がC++を始めたとき、最初に私が思いついたのは、もはや必要のないオブジェクトを破壊/削除/ファイナライズする方法でした。 Javaを使用しC++のデストラクタ(javaと比較)

私はnullにそれらを設定するために使用されるので、ガベージコレクタはそれの世話をしました。 しかし、私はC++でどのように価値があるのか​​分かりません。私はほとんどの私の質問を解決したこの記事http://en.wikipedia.org/wiki/Comparison_of_Java_and_C%2B%2Bを見つけました。しかし、まだ理解していないことがいくつかあります。 Javaでは

1)それが実行する前に積み重ねるためにいくつかのゴミを待っているので、常に有用ではありませんスポット()上で右きれいにガベージコレクタを強制する方法があります。 C++でこれを行う方法はありますか?

2)(C++)また、上記とは逆に、オブジェクトを「削除済み」の状態にして、プログラムがいつ(Javaのように)削除するかを決定する方法は?

3)(C++)私はスポット(私はそれが正しい方法ではないかなり確信しているが、私は念のために求めています)を右きれいにbarbageコレクタを強制すべきか?

あなたはコードが何をトリガすると、小さなコードの例を与えることができれば、私はそれをappriciateでしょう。

+9

C++はガベージコレクションを提供していません(実装することはできますが、お尻には本当の痛みがあり、通常は必要ありません)。代わりに[RAII](http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization)があり、デストラクタは非常に便利です。本を探す: –

+5

C++とJavaは、車や列車とはまったく異なっています。 –

+2

リンク先の記事を読んだことがありますか? C++にはガベージコレクタがありません。あなたの質問は意味をなさない。 –

答えて

4

C++はので、ここで簡単に説明します、この分野でのJavaよりも非常に異なっています。
構成:オブジェクトは使用準備されています。
破壊:オブジェクトはすべてを「終了」し、自身を逆アセンブルします。
割り当て解除:メモリがシステムに戻されます。

機能が終了すると、(私たちは自動呼び出し)関数自体のすべての変数は、そのデストラクタが呼び出され
int main() { 
    int myint; //automatic int object is allocated and constructed 
    //stuff 
} // when main ends, automatic int object is destroyed and deallocated 

int main() { 
    int* mypointer; //automatic pointer object is allocated and constructed 
    mypointer = new int; //dynamic int object is allocated and constructed 
    //stuff 
    delete mypointer; //dynamic int object is destroyed and deallocated 
} // when main ends, automatic pointer object is destroyed and deallocated 
    // note: Pointers to _not_ delete the object they point to. 

class myclass { 
    //members 
public: 
    myclass() {} //this is the default constructor 
    myclass(const myclass& rhs) {} //this is the copy constructor 
    myclass& operator=(const myclass& rhs) {return *this} //this is the assignment operator 
    ~myclass() {} //this is the destructor 
}; 

、その後、それらは自動的に解放されます。これは、関数のローカルオブジェクトを意味し、自動的に自身をクリーンアップします。インスタント関数が終了します。これは、クラスのメンバーにも魔法のように適用されます。それが破壊されると、それぞれのメンバーは自動的に破壊されます。これは、ほとんどのデストラクタが空であることを意味します。

手作業で(newキーワードを使用して)手作業を割り当てる場合は、手作業でdeleteキーワードを使用して破棄して割り当てを解除する必要があります。 deleteに電話をかけると、すぐそこで破壊(および割り当て解除)され、完了するまで続行されません。あなたが忘れてしまった場合、プログラムが終了したときにオペレーティングシステムの一部が割り当て解除されます。

の人がミスをしているので、あなたが動的なオブジェクトを必要なときに行うには、「正しい」ものがある:

int main() { 
    std::unique_ptr<myclass> myptr = new myclass(); //allocate and construct 
} //both the unique_ptr and the dynamic object are destroyed and deallocated 

unique_ptrが大きくためにあなたを解放し、自動的にそれがで指すものをクリーンアップするのに十分なスマートです懸念

C++は、そのファイルを表すオブジェクトがFの場合、そのファイルに排他ロックを設定する可能性があるためです。 C++では、一度Fが破壊されたら、すぐにを作成して、同じファイルを使用するオブジェクトGを作成することができます。 Javaでは、finalizerになり、が実行されるという保証はなく、プログラムが終了するまでファイルがロックされたままである可​​能性があります。 (無理だろう、しかし可能)

1

C++のガベージコレクションは、常に即時です。別のガベージコレクタはありません。オブジェクトを削除すると、現在のスレッドですぐに削除されます。

MyObject* foo = new MyObject(); 
... 
delete foo; 

は、C++で利用可能なガベージコレクションフレームワークがあり、そして、あなたはまた、ガベージコレクションの形態であるスマートポインタに見ることができます:それはこのようになります。以下

注ジェームズコメント - デストラクタと、オペレータがオブジェクトに対して削除は、常にすぐに呼ばれているが、それは実装依存メモリがすぐに利用できるようになりますかどうかなどです。

+3

C++で空きメモリを使用するとすぐに使用できるようになります。私は、別のスレッドに割り当てられていたメモリ解放が延期され、他の場合もそうである可能性が高いシステムを認識しています。 –

+0

そして 'delete'を呼び出さない限り、オブジェクトは到達不能になっても永久に割り当てられたままです。 –

+0

@JamesKanze - 私が間違っている場合は私を修正しますが、デストラクタ自体はすぐにすぐに呼び出されますか?メモリが将来の新しいステートメントのために利用できるようになるまでは、それは実装依存であると想像します。 –

6

1)あなたのオブジェクトが自動的に保存している場合は、その範囲を制限することができます完了したら、動的なストレージに、あなたがそれらを削除した場合

{ 
    X x; 
    //... 
} //x gets destructed here 

は:

X* x = new X; 
//... 
delete x; //x gets destructed 

2)あなたは(少なくともきれいな方法では)できません。オブジェクトを削除するときは、たとえその命令が末尾の括弧で構成されていても、C++に指示する必要があります。 C++には、ガベージコレクタはありません)

3(第1のコードスニペットを参照)。 2つのスニペットを参照してください。オブジェクトを明示的に削除する必要があります(動的ストレージの場合)。自動ストレージの場合は、自動的に削除されます(ガベージコレクタでは削除されません)。

調べる価値のあるものはスマートなポインタです(そこにはたくさんの実装があります)が、ガベージコレクタでもありません。メモリ管理の手間を省くことができます。しかし、それはJavaのようなものではありません。

+0

+1スマートポインタに言及します。スマートポインタについての非常に良い紹介があります(on stack overflow、http://stackoverflow.com/a/106614/1203803)。 C++ 11の標準ライブラリにはスマートポインタがあるため、Boostを使う必要はもうありません。 –

3

C++にガベージコレクタはありません。自分でデストラクタを作成して実行する必要があります。 C++では、デストラクタを実行するのを忘れるとよく​​あるエラーです。

オブジェクトにnewが割り当てられている場合は、deleteで削除する必要があります。したがって、newはコンストラクタを呼び出し、deleteはデストラクタを呼び出します。

myclass *p = new myclass(); 
// do something 
delete p; 

これは、動的オブジェクト割り当てと呼ばれます。

オブジェクトが「通常」と定義されている場合、オブジェクトはスコープ外になると自動的に破棄されます。

myclass a; 
// do something 
// will destructed when } 

これは自動オブジェクト割り当てと呼ばれます。

P.S.ガベージコレクタが発明されて以来、オブジェクトの削除を気にしないために、Javaでnullを割り当てることもできませんでした。

割り当て::メモリがオブジェクトのために確保されている

+1

「通常に定義された」をよりフォーマルなものに変更できますか?それが意味するものはあなただけが知っている。 –

+1

しようとしました。 C++では、Javaのようなオブジェクト "on heap"を作成することができます。この場合、オブジェクトへのポインタを受け取ります。最後に 'delete'に渡す必要があります。もう1つの方法は「通常」です。つまり、オブジェクトが「値で」作成されます。これは、整数型の場合にのみJavaで真です。 –

+3

ヒープとスタックは実装の詳細であり、このコンテキストではC++命名法の一部ではありません。用語は、自動および動的ストレージです。 C++でオブジェクトを割り当てる「通常の」方法はありません。 –

1

C++はRAII(リソース取得された初期化)プログラミングイディオムを使用して、Objective-Cの2にJavaやオートゾーンでガベージコレクタとして知られている自動メモリ管理のようなものは、適切なインスタンスのクリーンアップはこのようにありません簡単に複雑になることがあります。

ad 1:GCはありませんので、手動でオブジェクトを削除するか、またはC++ 11標準の一部である参照カウント手法またはより優れたスマートポインタを使用する必要があります。私が知っている限り、それはまだC++コンパイラでは利用できません。今のところBoostライブラリのスマートポインタテンプレートはhttp://www.boost.org/doc/libs/1_48_0/libs/smart_ptr/smart_ptr.htmです。新しいC++標準はBoost実装を直接採用したので、近い将来に新しい標準に切り替える際に問題は発生しません(MSVC 2012はC++ 11サポートを実装します)。

広告2:マーキングは不可能です。適切な場所で「手動で」削除するか、このタスクをスマートポインタに残してください。

ad 3:該当しません。

最後に、最も簡単なオプションがあります。オブジェクトをヒープ上に割り当てないでください。つまり、動的に意味します。 Javaではそのような可能性はありませんが、C++には存在します。 私はStroustrup(C++の作成者)の中には、C++の作成時にそのような動的な割り当てが推奨されていなかったC++プログラミングの素晴らしい本を読み込んでいます。彼は言い​​ました:RAIIを正しく動作させるためにはダイナミックな割り当てはしてはいけません - 今日は奇妙に思えますが、Stroustrupが書いたことです、それは私の頭ではない、私は個人的にすべての人が動くようにほぼすべてを動的に割り当てます...

静的割り当ての主な理由は、オブジェクトがスコープ外になったら削除されるため、例外の安全性とクリーンアップがまったく心配されないということです。インスタンスを動的に割り当てると、手動でインスタンスを削除しないと、インスタンスが現在のスコープから離れていれば自動的に削除されません(メモリリークが発生します)。シンプルなtry-catchブロックを考えてみましょう:

try 
{ 
Class *instance = new Class; 
//some error 
} 
catch(...) 
{ 
//error caught - current execution is terminated immediately, instance is no deleted - memory leak. 
} 

私は、Javaの例外がスローされたときに、必要なクリーンアップを実行できるように、常に、と呼ばれて最終的に文があります。しかし、C++では問題があります... 上記のスマートポインタやいくつかの非常に似たテクニックを使用していない限りです。スマートポインタを使用すると、これ以上クリーンアップを心配する必要はありません。間違いなく簡単になり、コードのバグも少なくなります)。

+0

メインのC++コンパイラ(MSVC、Intel、GCC、およびClang)はすべてC++ 11をサポートしています。サポートはコンパイラによって異なります。新しいスマートポインタは、主にライブラリ拡張であるため広くサポートされています。 VS 2010、gccは4.3にまで及ぶと思いますが、libC++のclangにはすべてのものがあります。 – bames53

+0

また、私は通常、動的記憶域割り当てをほとんど使用せず、自動記憶期間変数を使用することを好みます。 C++では、動的割り当てを直接使用する方が、皆さんのようにほぼすべてを動的に割り当てるというコメントよりもはるかに少ないことがわかります。 (それがまれでないなら、IMOの人々はC++を間違って書く)。ほとんどの場合、動的割り当てを直接使用する場合があります。動的配列の 'vector'のように、自分で直接行うのではなく、私のためにそれを処理する型を使用する方が好きです。 – bames53

+0

私の答えを明確にしてくれてありがとう。実際、私はスマートポインタのサポートについて知っていますが、私の答えを過度に複雑にしたくありませんでした。そして、はい、私は静的な割り当ても、おそらく動的なものよりも多く使用します。私はダイナミックな割り振りの見た目をより客観的に見て、そのために過度に使用されています:)しかし、私はそれが悪い習慣であるとは考えません。 – vitakot