• ベストアンサー

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