staticメンバ配列の初期化はどうすべきか – プログラミング – Home

staticメンバ配列の初期化はどうす...
 
通知
すべてクリア

[解決済] staticメンバ配列の初期化はどうすべきか


ホウジョウウサギ
 ホウジョウウサギ
(@ホウジョウウサギ)
ゲスト
結合: 18年前
投稿: 73
Topic starter  

環境:VS2005

以下のようなクラステンプレートで
staticなメンバである配列ms_Array[]を
例えば,「{0,1,2, ..., N-1}で初期化したい」のですが…

「該配列に初期値を入れたよフラグ(staticなbool型メンバ変数)を作って
 コンストラクタ内で,最初のインスタンスが値を入れる」
という書き方しか思いつきません.
より良い(? 一般的な?)方法は無いものでしょうか.

template< size_t N >
class CTest
{
private:
static int ms_Array[ N ]; //←この配列を初期化したい
};

template< size_t N >
int CTest< N >::ms_Array[ N ]; //実体定義


引用未解決
トピックタグ
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
 

> コンストラクタ内で,最初のインスタンスが値を入れる」
スタティックメンバーである以上、オブジェクトを生成せずに使用できるわけ
で、そうなればコンストラクタの走る余地はありません。

なので、以下のような感じで正解なのでは?
template< size_t N >
int CTest< N >::ms_Array[ N ] = {1, 2, 3 ,5}; //実体定義


返信引用
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
 

書いていて気づいた。

これだと、N が無意味ですね。


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

その初期値ってのがどういう性質かで話は違う・・・

CTest<2>::ms_Array と CTest<3>::ms_Array で初期値が違うのであれば
それは「初期値が違う」が故に template で記述するべきでない、のだろう。
逆に、すべての CTest<N> で初期値が同じ、であるなら、実用的には
その初期値はすべて0くらいしかありえないわけだけど。

あまりかっこよくない一例を挙げてみるテスト。

> 該配列に初期値を入れたよフラグ(staticなbool型メンバ変数)を作って
ここまでは同じ

> コンストラクタ内で,最初のインスタンスが値を入れる
これを避けるための「古典的」な方策であれば、たとえば

template<int N> struct test_t {
 static int (&static_arrayfunc())[N] {
  static int initdone;
  static int static_array[N];
  if (initdone==0) { /*初期化*/ initdone=1; }
  return static_array;
 }
};
などのように static メンバー関数のローカル変数として閉じ込めてしまうとか。
# マルチスレッドのための排他処理をしていないので実用に供する場合は注意。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

> # マルチスレッドのための排他処理をしていないので実用に供する場合は注意。

C++11(VS2012)なら call_once がつかえますねー

template<int N> struct test_t {
static once_flag flag;
test_t() { call_once(flag, [&](){ 初期化 });
};


返信引用
ホウジョウウサギ
 ホウジョウウサギ
(@ホウジョウウサギ)
ゲスト
結合: 18年前
投稿: 73
Topic starter  

しばらくネットの使えない状況下にあったため
放置状態になってしまいました.申しわけありませんでした.

問題の配列メンバはインスタンスが生成される前に参照されることはないので
とりあえずコンストラクタ内で一度だけ初期値を入れる形のままとしましたが,
初期化済を示すためのフラグをstaticメンバ関数無いに移す等くらいはできそうですね.

皆様,ありがとうございました.


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました