C++でFoo型のオブジェクトの配列があるとします。
Foo array[10];
Javaでは、次の方法でこの配列のオブジェクトをnullに設定できます。
array[0] = null //the first one
C ++でこれを行うにはどうすればよいですか?
代わりにポインタを使用してください:
Foo *array[10];
// Dynamically allocate the memory for the element in `array[0]`
array[0] = new Foo();
array[1] = new Foo();
...
// Make sure you free the memory before setting
// the array element to point to null
delete array[1];
delete array[0];
// Set the pointer in `array[0]` to point to nullptr
array[1] = nullptr;
array[0] = nullptr;
// Note the above frees the memory allocated for the first element then
// sets its pointer to nullptr. You'll have to do this for the rest of the array
// if you want to set the entire array to nullptr.
Javaとは異なり、nullptrへの参照を設定したときにメモリを自動的にクリーンアップするガベージコレクタがないため、C++でのメモリ管理を考慮する必要があることに注意してください。また、nullptrは、常にゼロではなくポインタ型であるため、これを行うための最新の適切なC++の方法です。
だから、ここでJavaを忘れてください、それはあなたを助けていません。自問してみてください; オブジェクトがnullになるとはどういう意味ですか?オブジェクトをnullにすることはできますか?答えはノーです。オブジェクトをnullにすることはできませんが、オブジェクトへの参照(C ++用語でのポインター)はnullにすることができます。
Javaには、内部のポインタに似た参照型があります。ただし、 Javaでもオブジェクトをnullに設定することはできず、参照のみに設定できます。
C ++では、本格的なオブジェクトとポインタ、およびオブジェクトへの参照があります。オブジェクト(またはプリミティブ型)へのポインターはnullにすることができますが、オブジェクト自体はnullにすることはできません。
したがって、オブジェクトの配列を作成すると、Foo
オブジェクトの配列がFoo
できます。あなたはポインタを持っていません、あなたはオブジェクトを持っています。配列がオブジェクトへのポインタnull
の配列である場合は、はい、それらを( C ++ 0xで)初期化できますnullptr
。つまり、有効なオブジェクトを参照していません。
あなたが持っている他の方法は、次のようにFooのポインターの1つの動的配列を使用することです:
Foo** array = new Foo*[10];// Pointer of array of pointers.
次に、このすべてのポインタをオブジェクトFooに初期化できます。
for(int i=0;i<10;i++)
array[i] = new Foo();// Give memory to pointers of object Foo in array
配列の1つの項目にnullを割り当てます。
array[0] = 0;
C ++では、NULLは0だと思います。これは、intまたは0が受け入れられる場所に割り当てることもできることを意味します。従来は、ポインタでのみ使用されていました。
このメモリを削除するには:
for(int i=0;i<10;i++)
delete array[i];
そして最後に
delete[] array;
コード例:
#include <iostream.h>
#include <stdio.h>
class Foo
{
private:
int a;
public:
Foo()
{
a = 0;
}
void Set_V(int p){a = p;}
int Get_V(){return a;}
};
int main()
{
Foo **array = new Foo*[10];
for(int i=0;i<10;i++)
{
array[i] = new Foo();
}
//array[0] = 0;
for(int i=0;i<10;i++)
array[i]->Set_V(i);
for(int i=0;i<10;i++)
cout<<array[i]->Get_V()<<endl;
for(int i=0;i<10;i++)
delete array[i];
delete[] array;
return 0;
}
では、新しい要素を作成せずに配列内の要素を「削除」する方法はありますか?つまり、ある種のアレイに穴を開けますか?
C ++では、配列がある場合:
Foo array[10];
次に、10個の要素すべてがデフォルトで構築されます。一般に、使用中の配列要素と「削除済み」の配列要素の概念はありません。このアイデアを追跡する1つの方法は、次のように、配列要素の実際の値をオプションにすることです。
boost::optional<Foo> array[10];
Boostライブラリのoptional<>
ライブラリについては、http: //www.boost.org/doc/libs/release/libs/optional/で読むことができます。
代替案を文書化するために、恐ろしいものを取り上げます。要素の1つでデストラクタを呼び出すことができます。array[3].~Foo();
配列自体がスコープ外になると、各要素のデストラクタが呼び出され、その前提条件は適切に構築されたオブジェクトを持つことであるため、これは非常に危険です。事前にその要素にFooを作成しておく必要があります(「配置」を使用)new
)。配列自体には、デストラクタが呼び出された要素を追跡するのに役立つものはありません。自分で追跡する必要があります(オブジェクト内にこれを記録しておくと、実際には機能する可能性がありますが、破壊後のオブジェクトは未定義の動作です)。すべてのコードパス(例外によるものを含む)で、一時的に使用されていない配列要素を追跡することに非常に注意する必要があります。あなたは本当にこれをしたくありません。
メモリを節約するために配列から要素を削除することが懸念される場合は、スマートポインタを使用してください。
shared_ptr<Foo> array[10];
その後、特定の配列要素を個別に制御できます。要素がスコープ外になると、まだ入力されている要素のみが破棄されます。適切なスマートポインタは、boostまたはC ++ 11で利用できます。または、使用することもできますstd::auto_ptr<>
が、事前にそのセマンティクスについて注意深く読んで、適切かどうか、および安全に使用する方法を確認する必要があります。
これとは別に、aがある場合は、Foo::operator=(Some_Type*)
を設定できarray[3] = NULL;
、その代入演算子が実行したことはすべて実行されarray[3]
ます。それでも、Foo
がポインタでない場合は、誰かがそれに割り当てることを許可することはおそらく悪い考えですNULL
。