ページ 11

C++ 動的配列の生成方法

Posted: 2011年9月12日(月) 18:11
by paw
動的確保について、下記ソース①②を例に出して、質問させてください。

コード:

#include <iostream>
using namespace std;

class hoge{
	int a;
public:
	hoge(){}
	hoge(int v_a){
		a = v_a;
	}
	int getter(){
		return a;
	}
};

int main(){
	hoge *hg = new hoge[100] ;
	for(int i=0; i<100; i++)
		hg[i] = hoge(i);
	
	for(int i=96; i<100 ; i++)
		cout << hg[i].getter() << endl;

	delete[] hg;
return 0;
}

コード:

#include <iostream>
using namespace std;

class hoge{
	int a;
public:
	hoge(){}
	hoge(int v_a){
		a = v_a;
	}
	int getter(){
		return a;
	}
};

int main(){
	hoge *hg[100];
	for(int i=0; i<100; i++)
		hg[i] = new hoge(i);

	for(int i=96; i<100 ; i++)
		cout << hg[i]->getter() << endl;

	for(int i=0;i<100;i++)
	delete hg[i];
return 0;
}
今まで②の方法を使っていまして、それを動的確保だと思っていました。
しかしよく考えれば
①は動的配列の確保
②は動的変数へのポインタの配列
だったんですね。

②の方が自然にコンストラクタを呼べて、使いやすいのですが、①を使った方が良いのでしょうか?
本を読んでも、どのサイトに行っても②の方法が使われていなくて不安です。
何か問題がある方法なのでしょうか。

また、もし②の方法を使うべきではないとすれば、コンストラクタで動的確保なんてことはできなくなりますよね?

質問というより、確認のようなものですが、アドバイスいただけると助かります。
どうぞよろしくお願いします

Re: C++ 動的配列の生成方法

Posted: 2011年9月12日(月) 18:31
by へろりくしょん
動的である事を前提に、インスタンスの配列が欲しいのか、ポインタの配列が欲しいのか、データ構造は設計に関わります。

どちらが良くてどちらが悪いというものではありません。
必要に応じて使い分けてください。

どちらにもメリット・デメリットがあります。

Re: C++ 動的配列の生成方法

Posted: 2011年9月12日(月) 19:00
by paw
やってはいけない方法、というわけではなかったんですね。
回答ありがとうございました。

Re: C++ 動的配列の生成方法

Posted: 2011年9月13日(火) 01:53
by ISLe
①はいったんすべての要素のデフォルトコンストラクタが実行されるので、それが余計に感じるときはありますね。

Re: C++ 動的配列の生成方法

Posted: 2011年9月13日(火) 11:30
by GRAM
paw さんが書きました:また、もし②の方法を使うべきではないとすれば、コンストラクタで動的確保なんてことはできなくなりますよね?
方法はほかにもあります。配置newを使う方法です
利点:
hogeのインスタンスが連続してメモリ上に存在する
コンストラクタ呼び出しが1度きり
もちろんoperator = の呼び出しも存在しない

欠点:
めんどくさい。注意を払わなくては簡単にバグを生み出す。

コード:

#include <iostream>
#include <new>
using namespace std;
 
class hoge{
    int a;
public:
    hoge(){}
    hoge(int v_a){
        a = v_a;
    }
    int getter(){
        return a;
    }
};
 
int main(){
    //まずメモリだけをドバっと確保してしまう。
    hoge* hg = static_cast<hoge*>( operator new( sizeof( hoge ) * 100 ) );
    for(int i=0; i<100; i++){
        //確保した領域にhogeを作る
        new( hg + i ) hoge(i);
    }   
    for(int i=96; i<100 ; i++)
        cout << hg[i].getter() << endl;
    //デストラクタを明示的に呼び出して
    for(int i=0;i<100;i++) hg[i].~hoge();
    //領域を解放する
    operator delete( hg );
    return 0;
} 


Re: C++ 動的配列の生成方法

Posted: 2011年9月13日(火) 15:44
by YuO
①形式なら,std::vectorで代替することも考慮した方がよいかもしれませんね。
reserve関数でcapacityを正しく設定すれば,再割り当ても抑えられますし。