• ベストアンサー

C++ メンバ配列の初期化

------------------------------------------- class Myclass {    int array[20]; public:    Myclass() {       for(int i=0; i<20; i++) {          array[i] = 0;       }    } }; -------------------------------------------- ↑のようにするとarrayが初期化ではなく、代入されるそうなんですが、何か良い初期化方法があれば教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

memsetによる初期化はいろいろ問題があるのでお勧めしませんが、int型の配列であれば実害はないので、状況次第では使ってもよいでしょう。 効率に関してですが、memsetの一般的な実装では、前後の半端を除けば、ワード単位で書き込みを行います。あるいは、ストリング命令やブロック転送命令があるプロセッサの場合は、最も効率のよいコードに展開されます(関数の呼び出しも発生しません)。 std::fillやstd::fill_nを使うと関数呼び出しのオーバーヘッドは発生しますので、効率のことをいうのであれば必ずしも最適ではありません。ただ、普通は一番よい選択だと思います。 いっそのこと、 class MyClass {  struct Member { int array[20]; } m; public:  MyClass() : m(Member()) {} }; のようにするのもよいと思います。 memsetよりはずっと健全ですし、STLが使えない場合でも大丈夫ですし、おそらくコンパイラは最も効率の良いコードを出力すると思います。

ioehd
質問者

お礼

難しいですが面白い話です。ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (4)

回答No.4

STLのfill_nはどうでしょうか。 #include <algorithm> std::fill_n(array, _countof(array), 0);

ioehd
質問者

お礼

目からウロコです。ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • Lchan0211
  • ベストアンサー率64% (239/371)
回答No.3

処理系にもよりますが、この場合memsetの方が速いというのは幻想だと思います。 結局memset関数の中で、ループしてメモリを初期化しています。 しかも、memsetは、バイト単位の初期化になるため、 int20個の初期化は80回ループになります。 memset関数を呼び出すための関数呼び出しオーバーヘッドもあります。 処理系によっては、memsetをインラインで最適化して 処理してしまうケースもあると思いますが、 結局、質問に書かれているコーディングの通り、 int型変数(32ビット領域)に0を代入する処理を20回繰り返す処理を記述するのが 性能的に最も最適化されたコーディングだと思います。 ただ、memsetで初期化処理を記述する方がわかりやすいので、 メンテナンス性を考慮して、memsetにすべきという意見はあると 思います。私も特に性能を考慮する必要がない限りmemsetを使います。 今回のケースは、たいして複雑な初期化でもないし、 性能差もnsecレベルの話だと思うので、どちらでもよいと思います。

ioehd
質問者

お礼

詳しく説明していただき分かりやすいです。参考になります。

全文を見る
すると、全ての回答が全文表示されます。
回答No.2

別に良いと思いますが、少しでも実行速度を上げたい場合は、mensetの方が良いと思います。 (自分でfor文で初期化すると少し実行速度が落ちます。) memset(array,0,sizeof(array));

ioehd
質問者

お礼

ご回答ありがとうございます。勉強になります。 memsetはレジスタでも使ってるんですかね?そのうち調べてみたいと思います。

全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

int型の配列であれば、代入になっても大差はないので、そのままでもよいのではないでしょうか?

ioehd
質問者

お礼

私の中ではこのやり方に迷いが会ったのですが、おかげ様で自信が持てました。ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • C/C++の配列について

    配列の作り方について nは特定の数でarr[3]以降の値をfor文で代入したいのですが 同じfor文で値を代入すると(1)は不正解で(2)が正解になります 小さい数だと見た目は同じで何が違うのか解らないのですが、これは何がちがうのでしょうか? (1)の0, 0, 1以降は全て初期値として0が入ると認識してたのですがそれも違いますか? (1) int arr[n]={0, 0, 1}; (2) int arr[n]; arr[0]=0; arr[1]=0; arr[2]=1; for (int i=3; i<n; i++) { arr[i]=略 } よろしくお願いします

  • Vector ClassのVector配列

    Vector配列からVector配列への代入などのアクセスは問題なく行えるのですが、 Vectorを入れ子にした場合?にエラーが生じてしまいます。 Class Myclass{ public: vector <int> num; }; vector <Myclass> obj; ・・・・ vector <Myclass>::iterator it=obj.begin(); vector <int> work; ・・・・ it->num=work; とするとエラーになってしまいます。 代入以外のresize()などのアクセスもエラーになってしまいますが、 vector が入れ子になっていることが関係しているのでしょうか? ご教示願います。

  • クラスがメンバーとしてクラスを持つ時の宣言について

    自作クラスMainClassがMyClassというクラスをメンバー変数として持つ場合、宣言時に引数をいくつか持つコンストラクタを呼び出そうとすると構文エラーとなります。 class MyClass { public: MyClass(int, int); } class MainClass { private: MyClass myclass(10,10); } このような宣言はできないのでしょうか。 引数なしのコンストラクタは呼び出せているようです。

  • C言語 初期化について

    はじめまして。 C言語を学習しております。 【初期化】の意味について混乱しております。 今まで、【初期化】とは下記のような繰り返しのある文に初期値(数え始めの値、下記の例では1)を代入することだと思っていました。 for (i = 1;i <= 10;i++) { printf("メッセージ\n"); } しかし、勉強が進むにつれ、下記のように様々な場面で【初期化】という言葉が出てきたことで、【初期化】の意味がわからなくなりました。 ●【文字変数の配列の初期化】の例 char str[6] = {'M','A','R','I','O'}; ●文字列リテラルを用いた【文字列の初期化】の例。 #include <stdio.h> int main(void) { char str[] = "MARIO"; printf("%s\n",str); return 0; } ●【配列の初期化】の説明 型名 配列名[要素数]={0番の数値,1番の数値,2番の数値,・・・}; ●【配列を初期化】して表示する例 #include <stdio.h> #include <stdio.h> int main(void) { int array[10] = {42,79,13}; printf("array[0] = %d\n",array[0]); printf("array[1] = %d\n",array[1]); printf("array[2] = %d\n",array[2]); printf("array[3] = %d\n",array[3]); printf("array[4] = %d\n",array[4]); return 0; } ●for文の説明 for (初期化;条件式;更新) { 繰り返す文; } 初期化とは、カウント変数の初期化を行うための文です。 ここに書かれた式は、最初に1回だけ実行されます。 【初期化】とは、場面場面で意味が変わるのでしょうか。 どの場面に通じる【初期化】の本来の意味を教えてください。 よろしくお願い致します。

  • C言語の配列とポインタについて

    C言語の配列とポインタについてわからないことがあります。 以下のソース例は、10個の値の平均値を求めるプログラムです。 コメントを挟んだ部分が疑問点です。 【ソース例】 #include <stdio.h> int getaverage(int *data); int main(void) { int average,array[10] = {15,78,98,15,98,85,17,35,42,15}; average = getaverage(array); printf("%d\n",average); return 0; } int getaverage(int *data) { int i,average = 0; for (i = 0;i < 10;i++) { average += data[i]; /*ポインタ変数なのに? */ } return average / 10; } 【実行例】 49 このdata[i]はポインタ変数であり、 配列arrayの i 番目の要素であるarray[i]の"アドレス" が代入されているはずだと思うのですが、 なぜ通常の整数変数であるaverageと数値計算が出来、正しい結果が出たのでしょうか? あたかもdata[i]には、 array[i]の"アドレス"ではなく、 array[i]の"メモリの中身"が代入されているようです。 どういうことでしょうか? 回答よろしくお願いします。

  • STL vectorの初期化

    STL vectorの初期化についてなんですが 以下のようなクラスのprivateなメンバ変数としてvectorを定義し それをメソッド内のループ処理にて初期化しながら使用したいのですが 初期化の仕方が分かりません。コンストラクタを呼べば初期化されるようですが 以下のようにヘッダとソース内で2度同じような宣言をしてしまっても問題ないのでしょうか? //=== test.h === class test { private : vector<int> array; public : int fnc(); }; //=== test.c === int fnc() { for (int i = 0; i < 10; i++) { //★ここで初期化したい vector<int> array;  ←これで問題ないか? for (int j = 0; j < 10; j++) { array.push_back( md ); } } } C#などでは宣言とインスタンス生成を別に分けられたのですがC++も同様の事が出来るのでしょうか? 一応「array = new vector<int>;」といれて見たのですがエラーが出ました。

  • C++ 動的確保について

    学校の演習課題で「クラス Array のメンバ変数を以下のように変更して,配列のサイズを実行時に決められるようにしたい.コンストラクタを適切に修正しなさい.配列のサイズはコンストラクタの引数で指定できるようにすること.main 関数内のオブジェクトの宣言部分を適当に変更して動作を確認しなさい.」という課題が出ました。 指示のメンバ変数の変更は、sizeを定数にしていたものを変数にし、arrayを配列からポインタにする点です。 もとのプログラムはI、私がいじったものがIIです。どうにもセグメンテーションフォルトから抜け出せなくて困っています。どのようにしたら題意のプログラムになるのでしょうか? よろしくお願いします。 ここからI~ #include <iostream> using namespace std; class Array{ private: const static int size = 6; int array[size]; public: Array( ); int getSize( ); void put( int index, int data ); int get( int index ); void show( ); }; Array::Array( ) { for ( int i = 0; i < size; i++ ) { array[i] = 0; } } int Array::getSize( ) { return size; } void Array::put( int index, int data ) { array[index] = data; } int Array::get( int index ) { return array[index]; } void Array::show( ) { cout << "| "; for ( int i = 0; i < getSize( ); i++ ) { cout << get(i) << " | "; } cout << endl; } int main( ) { Array array1; array1.put(1, 2); array1.put(4, 1); array1.show( ); return 0; } ~ここまでI ここからII~ #include <iostream> using namespace std; class Array{ private: int size; int *array; public: Array(int s); ~Array(); int getSize(); void put(int index, int data); int get(int index); void show(); }; Array::Array(int s) { size = s; array = new int; for (int i = 0; i < size; i++) { *array = 0; array++; } array -= size; } Array::~Array() { delete[] array; cout << "デストラクタが呼ばれました。配列の要素数分のメモリを開放します." << endl; } int Array::getSize() { return size; } void Array::put(int index, int data) { *(array + index) = data; } int Array::get(int index) { return *(array + index); } void Array::show() { cout << endl << "| "; for (int i = 0; i < getSize(); i++) { cout << get(i) << " | "; } cout << endl; } int main() { int s = 0; cout << "確保するサイズを入力してください:"; cin >> s; Array array1(s); array1.put(1, 2); array1.put(4, 1); array1.show(); return 0; } ~ここまでII

  • 配列であるメンバのコンストラクタを呼ぶ方法

    C++のクラスについて教えていただけないでしょうか。以下のような場合、 class ClassA {   int A; public:   ClassA(int a): A(a) {} }; class ClassB {   ClassA A; public:   ClassB(): A(10) {} }; class ClassC {   ClassA A[2]; public:   ClassC() {} //配列であるメンバのコンストラクタを呼び出したい }; ClassBがClassAのコンストラクタを呼ぶには上記のような方法で良いと思うのですが、ClassCのようにメンバが配列の場合、そのメンバのコンストラクタを呼ぶにはどのようにしたら良いのでしょうか。ご教授をお願いします。

  • STLのvectorで作った配列をメンバ変数にする場合は。。。

    C++初心者です。 STLのvectorで作った配列をメンバ変数は 以下のように宣言し、 class Array { public: vector<int> array; void Set(); } Array::Setのメンバ関数でarrayに値をセットします。 そして、メインからarrayを参照しようとしましたが 値が入っていませんでした。 メンバ変数の宣言の仕方が良くないのですか?

  • C++ クラスをメンバにもつクラスについて

    お世話になります。C++初心者でうまくコードが書けません(><) クラス1と2があり、クラス1のメンバにはクラス2があります。 メインでクラス1をインスタンス化してクラス2のfunc2を呼び出します。 func2ではクラス1のインスタンスから呼び出された場合にクラス1の m_int1を取得します。 Class Class1{ public:  int m_int1;  Class2 m_Class2; }; Class Class2{ public: void func2(); }; void Class2::func2(){  /*ここの記述方法が分かりません*/  /*C1から呼び出されたらC1のm_int1に100を入れる*/  /*以下間違え*/  class1 C2_1;/*別のclass1のオブジェクトなのでこれに入れてもダメっぽい*/  C2_1.m_int1 = 100; } void main(){  class1 C1;  C1.m_int1 = 10;  C1.m_class2.func(); } C1.m_class2.func()の中から呼び出したC1にアクセスする方法が 分かりません(TT)。実体がまだあるのだからアクセスする方法は あると思うのですが・・・ どなたかよろしくお願いします。