none
C++における動的配列の使い方について RRS feed

  • 質問

  • C++の動的配列の使い方についてです。

    初心者なんですが、ウェブとかでC++を勉強しているところです。

    動的配列を使いたいのですが、結構コンパイルエラーが出たり、実行時におかしくなったりして、動的配列の使い方がよくわかっていないのです。ちょっと動的配列を使う簡単なプログラムを作製したんですが、以下の使い方で大丈夫でしょうか?また最後に配列サイズを出力しているんですが、なぜか異なる値が出力されています。なんででしょうか?

    #include<iostream>
    
    class vector{
    public:
      int n;
      double *x = new double[n];
    
    };
    
    int main(){
    
      vector vec;
      vec.n=10;
    
      int i;
      for(i=0;i<10;i++){
    
        vec.x[i]=(double)i;
    
        std::cout<<vec.x[i]<<"\n";
    
      };
    
    std::cout<<sizeof(vec.x)<<"\n";
    std::cout<<sizeof(vec.x[0])<<"\n";
    
    }
    よろしくお願いいたします。


    2017年8月29日 8:26

すべての返信

  • ご質問のプログラムでは、main 関数の vector vec; の行が実行されたときに、vector クラスのメンバの配列 x が確保されます。vec.n = 10; の前に配列が確保されてしまいますので、vector メンバの n は不定値で配列が確保されるようになっています。

    これを解消するには、配列を確保する前に n を設定する必要があります。例えば下記のようにクラスのコンストラクターで n の値を設定するようにするとよいと思います。

    class vector2 {
    public:
    	vector2(int size) : n(size) {} // クラスのコンストラクターで n の値を設定
    	const int n;
    	double *x = new double[n];
    };
    
    // クラスの使用
    vector2 vec(10);


    ※配列 x は解放されていないので、クラスのデストラクターなどで解放する必要があります。

    また、動的に確保された配列のサイズは sizeof で取得することができません。確保したサイズを覚えておくか(ご質問のプログラムの場合は n を使う)か、動的配列として代わりに std::vector を使うことをお勧めします。

    2017年8月29日 9:04
  • 勉強のために「頭のいい配列クラスを作ってみようとしてる」と解釈します。

    1.class vectorは配列の個数と、確保したポインタを外部にいじられてはいけません。
     private:か、protectedにしましょう。

    2.個数を与えて、配列を確保する関数が必要になります。
     void Alloc( int ex_AlcNum){
        if( x != nullptr)  delete [] x; // 既に確保済みなら破棄する
        n = ex_AlcNum; // 新しい個数
        x = new double[ n];
      }
      みたいなやつですね。

    3.ポインタxが外部から参照できなくなってしまったので、その手段を
     コードしなければなりません。
     double & operator[]( int ex_Indx){
        return x[ ex_Indx];
      }
      のようなオペレータがあると
      vector vec;
      vec.Alloc( 10);
      vec[ 5] = 5000; // vec.x[5]に5000を入れる
     の様に使えるようになります。

    4.個数を与えて構築できるコンストラクタがあると便利。
      vector( int ex_AlcNum){
         n = 0;
         x = nullptr;
         Alloc( ex_AlcNum);
      }
      でOK。

    class MyVector
    {
    private:
    	int      n;
    	double * x;
    public:
    	//デフォルトのコンストラクタ
    	MyVector(){
    		n = 0;
    		x = nullptr;
    	}
    	// 確保数指定のコンストラクタ
    	MyVector( int ex_AlcNum){
    		n = 0;
    		x = nullptr;
    		 Alloc( ex_AlcNum);
    	}
    	// デストラクタで確保した配列を破棄
    	~MyVector(){
    		if( nullptr != x) delete [] x; // 全て破棄
    	}
    	// 配列の確保
    	void Alloc( int ex_AlcNum){
    		if( nullptr != x) delete [] x; // 全て破棄
    		n = ex_AlcNum;
    		x = new double[ n];//確保
    	}
    	//指定インデックスの要素の参照を戻す
    	double & operator[]( int ex_Indx){
    		return x[ ex_Indx];
    	}
    };
    // 使ってみる
    void foo()
    {
    	MyVector vec( 10);
    	vec[ 5]	= double( 3.14);
    }
    

    2017年8月29日 11:25
  • 問題点については、ほとんど、お二方が指摘されていますが、、、

    sizeof について間違えているような気がします。

     sizeof(vec.x) : double の配列サイズで無く、 doubleへのポインタサイズを取得します。
         sizeof(double *) となって、32bitだと 4 でしょうか。

     sizeof(vec.x[0]) : sizeof(double) なので、8 だったでしょうか。

    参考までに。

    2017年8月29日 12:55
  • >動的配列を使いたい

    もし作りたいではなく、使いたいという事なら、標準ライブラリの vector を利用すればよいかと思います。

    「C++ vector」 などで検索してみてください。

    一例 ↓

    C++ 動的配列クラス std::vector 入門
    http://vivi.dyndns.org/tech/cpp/vector.html

    2017年8月31日 0:49
  • hamahama6 さん、こんにちは
    フォーラム オペレーターの立花楓です。

    本件についてその後いかがでしょうか。

    課題が解決されたのであれば幸いですが、寄せられている情報を確認いただき、なにか進展がございましたらこちらのスレッドへご返信いただけますと幸いです。

    また、ご確認いただいた際にお寄せいただいた情報がお役に立った場合は、 [回答としてマーク] をお願いいたします。

    よろしくお願いします。


    MSDN/TechNet Community Support 立花楓

    2017年9月7日 7:20
    モデレータ