2011-11-28 25 views
8
int& foo() { 
    printf("Foo\n"); 
    static int a; 
    return a; 
} 

int bar() { 
    printf("Bar\n"); 
    return 1; 
} 

void main() { 
    foo() = bar(); 
} 

最初に評価する必要があるかどうかはわかりません。代入演算子のC++関数評価順序

私はVCでバー機能を最初に実行しようとしました。しかし、g ++(FreeBSD)によるコンパイラでは、最初に評価されたfoo関数を出力します。

多くの興味深い質問は、上記の問題から派生し、私は前の結果に基づいて、動的な配列(のstd ::ベクトル)

std::vector<int> vec; 

int foobar() { 
    vec.resize(vec.size() + 1); 
    return vec.size(); 
} 

void main() { 
    vec.resize(2); 
    vec[0] = foobar(); 
} 

があると、VCは(foobarのを評価し)、その後、ベクトルを行いますオペレーター[]。そのような場合には問題ありません。しかし、gccではvec [0]が評価されているので、foobar()関数は配列の内部ポインタを変更する可能性があります。 vec [0]は、foobar()の実行後に無効にすることができます。

は、それは我々が評価の

void main() { 
    vec.resize(2); 
    int a = foobar(); 
    vec[0] = a; 
} 
+3

+2、これは興味深い質問です。それは私が以前考えたことがないものです。とにかくそのようなコードを使用し始めると明らかにあなたは困っています:) –

+0

+1。それは本当に面白い質問です。それ以上に質問は非常にきれいに聞かれます。よく書かれた質問。 – Nawaz

+1

私はこの今日の興味深い例を見つけました: 'auto_ptr p(new int); smart_map m; 'smart_map :: operator []'が投げる可能性があるとすれば、 'auto_ptr'が所有権を解放しても、マップは所有権を引き継ぐことはできません。 RHSがLHSの前に評価されるケース。 ( 'smart_map'はSTL' map'と似ていますが、破壊時に各キーと値のペアのポインタ値を削除することを除けば) – mrkj

答えて

8

注文が、その場合には、不特定のだろうと、このようなコードを分離する必要があることを意味しています。そのようなコードを

同様の例を記述し、式の評価のhere

0

受注予期しない動作ある。いけません
コンパイラが評価することを選択した順序によって異なります。

shuchコードを書くことを控えてください。
副作用がなければ、順序は重要ではありません。注文事項は、その後、あなたのコードが間違ってある場合

/がないポータブル/**は異なるコンパイラaccross異なる結果を与えることができます。

5

評価の順序を定義するかどうかを決定するC++の概念は、sequence pointと呼ばれます。

基本的に、シーケンスポイントでは、そのポイント(観察可能な副作用を伴う)より前のすべての式が評価され、そのポイントを超える式はまだ評価されていないことが保証されます。

驚くべきこともありますが、代入演算子はシーケンスポイントではありません。すべてのシーケンスポイントの完全なリストはWikipedia articleです。

+2

... _was_はシーケンスポイントと呼ばれます。今年から、_sequenced before_/_sequenced after_を使用しています。 – MSalters

+0

@MSalters:それを指摘してくれてありがとう - 知らなかった! –