オブジェクトの動的制御

newとdelete演算子

C言語ではメモリの確保にmalloc、解放にfreeを使っていました。C++でもmallocやfreeを使えますが、C++では新たにnewとdelete演算子というものが導入されました。これらnewとdeleteを使うことで、mallocやfreeよりもすっきりとしたコードを書くことができます。ここでは、newとdelete演算子の使い方を紹介します。

newとdelete

C++ではnewとdelete演算子により、メモリの動的に制御を行うことができます。

new演算子の使い方は以下の通りです。

ポインタ=new データ型;

指定したデータ型の分だけメモリを確保します。delete演算子の使い方は以下の通りです。

delete ポインタ;

これによりメモリが開放されます。例えば、以下のプログラムのように使用します。

#include <iostream>
using namespace std;

int main(void){
	int *p;
	p=new int;	//int型のメモリを確保
	*p=10;
	cout<<*p<<"\n";
	delete p;	//メモリを解放
	return 0;
}

実行すると以下のようになります。

10

配列用のメモリを確保する場合

メモリの確保はたいてい配列を確保する際に使います。

new演算子で配列を確保するには

ポインタ=new データ型[配列数];

とします。メモリを削除するには

delete [] ポインタ;

とします。では試しにプログラムを組んでみましょう。

#include <iostream>
using namespace std;

int main(void){
	int i,n;
	cout<<"配列数:";
	cin>>n;

	int *p;

	p=new int[n];	//int型のメモリを確保
	for(i=0;i<n;i++){
		p[i]=i;
	}
	for(i=0;i<n;i++){
		cout<<p[i]<<"\n";
	}

	delete [] p;	//メモリを解放
	return 0;
}

実行すると以下のようになります。

配列数:5
0
1
2
3
4

このプログラムでは

	cout<<"配列数:";
	cin>>n;

で配列数を取得し

	p=new int[n];	//int型のメモリを確保

により配列のメモリを動的に確保しています。その後、

	for(i=0;i<n;i++){
		p[i]=i;
	}

で配列に値を入力して

	for(i=0;i<n;i++){
		cout<<p[i]<<"\n";
	}

でコンソールへ表示させています。最後に

	delete [] p;	//メモリを解放

によりメモリを解放しています。

メモリ確保に失敗した場合

もちろん、メモリを確保するのに失敗する場合があります。その場合は、例外を生成するので、それにより判断します。よって、上記のようなプログラムではなく

#include <iostream>
using namespace std;

int main(void){
	int i,n;
	cout<<"配列数:";
	cin>>n;

	int *p;

	try{
		p=new int[n];	//int型のメモリを確保
	}catch(bad_alloc xa){
		cout<<"メモリの確保に失敗\n";
		return 1;
	}
	for(i=0;i<n;i++){
		p[i]=i;
	}
	for(i=0;i<n;i++){
		cout<<p[i]<<"\n";
	}

	delete [] p;	//メモリを解放
	return 0;
}

のようにtry-catch文でメモリ確保に失敗した処理もかくようにしましょう。標準C++では例外を生成するのですが、古いC++コンパイラの場合は単にヌルを返すことがあります。ヌルを返す場合は以下のようにチェックします。

	p=new int[n];	//int型のメモリを確保
	if(!p){
		cout<<"メモリの確保に失敗\n";
		return 1;
	}

多次元配列

最後に多次元配列の確保について解説します。例えば、2次元配列(n,m)のメモリの確保では

		int **p;
		p=new int* [n];	//nこ分のint型ポインタを確保
		for(i=0;i<n;i++){
			p[i]=new int[m];	//mこ分のintを確保
		}

とします。まず、int型のポインタを

p=new int* [n];	//nこ分のint型ポインタを確保

でn個確保します。そして、n個のポインタそれぞれにm個のint型のメモリを

		for(i=0;i<n;i++){
			p[i]=new int[m];	//mこ分のintを確保
		}

で確保します。解放では

	for(i=0;i<n;i++){
		delete [] p[i];
	}
	delete [] p;	//メモリを解放

とします。

	for(i=0;i<n;i++){
		delete [] p[i];
	}

で、ポインタp[i]のm個のint型メモリを開放します。そして

delete [] p;	//メモリを解放

で、n個のポインタp[i]のポインタpを開放します。

以下にプログラム例を示します。

#include <iostream>
using namespace std;

int main(void){
	int i,j,n,m;
	cout<<"配列数:";
	cin>>n;
	cout<<"配列数:";
	cin>>m;

	int **p;

	try{
		p=new int* [n];	//nこ分のint型ポインタを確保
		for(i=0;i<n;i++){
			p[i]=new int[m];	//mこ分のintを確保
		}
	}catch(bad_alloc xa){
		cout<<"メモリの確保に失敗"<<xa.what()<<"\n";
		return 1;
	}
	for(i=0;i<n;i++){
		for(j=0;j<m;j++){
			p[i][j]=i+j;
		}
	}
	for(i=0;i<n;i++){
		for(j=0;j<m;j++){
			cout<<p[i][j]<<",";
		}
		cout<<"\n";
	}

	for(i=0;i<n;i++){
		delete [] p[i];
	}
	delete [] p;	//メモリを解放
	return 0;
}

実行すると

配列数:3
配列数:4
0,1,2,3,
1,2,3,4,
2,3,4,5,

と表示されます。

著者:安井 真人(やすい まさと)