C++でも、クラスやオブジェクトをもちろん扱うことができますが、その前にメモリの概念を押さえておく必要があります。
C++におけるメモリの概念
- 自動メモリ
- フリーストア
自動メモリ
オブジェクトが自動的に管理されるメモリです。サイズは小さいです。VC++で1MB程度です。スタックメモリ領域を使います。
特に明示的に開放しなくても、ブロックの終わりで解放されます。(例えば、main関数の完了時に解放されます。)
フリーストア
オブジェクトをプログラマが管理するメモリ領域。ヒープメモリ領域に格納されます。「動的メモリ」とも呼ばれます。
特徴としては、自動メモリ領域よりも大きいです。
クラスのオブジェクトを宣言する構文
ポインタを使わない場合
オブジェクトは「自動メモリ」に配置されます。
新規作成
1 2 3 |
型 変数名 または 型 変数名{} |
すでにあるオブジェクトをコピーして作成する場合
1 2 3 4 5 |
型 変数名(同型のオブジェクト) または 型 変数名{同型のオブジェクト} または 型 変数名 = 同型のオブジェクト |
ポインタ(new)を使う場合
オブジェクトは「フリーストア」に配置されます。
新規作成
1 2 3 4 5 |
型* ポインタ変数名 = new 型 または 型* ポインタ変数名 = new 型{} または 型* ポインタ変数名 = new 型() |
ポインタ変数からオブジェクトにアクセスするには下記の構文を使います。
1 |
*ポインタ変数名 |
すでにあるオブジェクトをコピーして作成する場合
ポインタを使う場合でもコピーは可能です。
1 2 3 |
型* ポインタ変数名 = new 型(同型のオブジェクト) または 型* ポインタ変数名 = new 型{同型のオブジェクト} |
オブジェクトの解体
「フリーストア」に配置されたオブジェクトはブロックの終わりで解体されません。
プログラマが明示的に開放してあげる必要があります。
下記の構文を使って、定義したポインタ変数を解放してあげましょう。
1 |
delete ポインタ変数名; |
解放し忘れると、フリーストア内に使われないオブジェクトが放置されてメモリリークの原因になるので注意です。
「自動メモリ」と「フリーストア」でどのように使い分ければよいのか?
では、オブジェクト作成はどちらの宣言もできますが、どのように使い分ければよいのでしょうか。
メモリの管理が面倒なので、基本的には自動メモリ(newを使わない方)を使うようにしましょう。
ただ、自動メモリは小さいので、入りきらないような大きなオブジェクトを構築する場合は、ポインタ変数を使ったフリーストアにオブジェクトを構築するようにしましょう。
ただ、フリーストア領域のメモリ管理は面倒ですし、危険ですよね。そのために用意されたC++の機能である「スマートポインタ」というものがあります。
スマートポインタとは?
動的に管理するのは非常に面倒です。そこで用意された仕組みが「スマートポインタ」になります。
スマートポインタで管理されるオブジェクトは自動的に管理されるため、明示的にdeleteを使わなくても自動開放されます。
スマートポインタが定義されているヘッダ
<memory>で定義されており、下記の二種類があります。
- std::unique_ptr
- std::shared_ptr
std::unique_ptr
コチラの方が早い。
std::shared_ptr
コチラの方が簡単に扱うことができる。
参照ポインタとは?
C言語にはない機能で、関数の引数にポインタを渡す場合に使うことができる機能です。
通常のポインタであれば、下記のような関数を宣言した場合は、
1 |
void func(int* a); |
下記のように渡す必要があります。
1 2 |
int a; func(&a); |
ただ、「参照ポインタ」を利用した場合は、「*」の代わりに「&」を利用します。
1 |
void func(int& a); |
渡す際に「&」を記述する必要がなくなります。
1 2 |
int a; func(a); |
この記事へのコメントはありません。