2012-09-06 15 views
13

私はこのコードを持っている:「初期化子要素はコンパイル時定数ではありません」:"Initializer要素はコンパイル時定数ではありません"なぜですか?

- (NSString *) calculate: (uint) position { 
    static NSArray * localArray = [NSArray arrayWithArray: self.container.objects ]; 
    // some un related code 
    return obj; 
} 

コンパイラが言って文句を言います。 localArrayに "static"を追加したときに起こったことです。しかし、なぜ?

+0

http://stackoverflow.com/q/6143107/94687と同じ質問でした。あなたの質問の唯一の特別なことは、静的なキーワードを関数本体の中の変数に明示的に追加することです(しかし、これは、その質問のようにグローバルスコープに変数を持たせることと同じでなければなりません)。 –

答えて

28

[NSArray arrayWithArray: self.container.objects ]はコンパイル時定数ではないため、実行時に評価する必要がある式です。 CとObjective-Cでは、staticの関数内の変数は、のコンパイル時の定数の定数で初期化する必要がありますが、C++とObjective-C++はより緩やかで非コンパイル時定数を許可します。

どちらかのObjective-C++のようにコードをコンパイル、またはこのような何かにそれをリファクタリング:コンパイラが使用して初期化static変数のボンネットの下に生成するコードにかなり似ている

static NSArray *localArray = nil; 
if (localArray == nil) 
    localArray = [NSArray arrayWithArray: self.container.objects ]; 

実際には、nilなどのセンチネル値を使用するのではなく、値が初期化されたかどうかを示す第2のグローバルフラグを使用します(この場合、localArrayは決してnilではないと仮定しています)。コンパイラの逆アセンブリをチェックすることができます。

+2

'localArray'を初期化するためには' dispatch_once() 'を使うことをお勧めします。スレッドセーフで非常に効率的です。 – bbum

5

実行時に認識または変更される静的でない値を持つ静的変数を初期化することはできません。

static NSArray *localArray = nil; 
localArray = ...; 

最初の命令は、アプリのライフサイクルに一度実行されます。

あなたは、おそらくこのような何かを行う必要があります。 2番目の命令は、calculate:メソッドが呼び出されるたびに実行されます。

静的変数を使用すると、正しく実行されないとバグのある動作につながることがあるので、これらの変数では不安が感じられる場合は、使用しないでください。

+2

+1 "最初の命令はアプリのライフサイクルで一度実行されます。" – Philip007

関連する問題