2013-03-15 15 views
15

po prostu dowiedzieć się, że ten mały kawałek kodu C++ nie daje mi ten sam wynik z brzękiem ++ i z g ++:C++ odniesienia na statycznej zmiennej

#include <iostream> 
#include <string> 

using namespace std; 

const string& createString(char c) { 
    static string s; 
    s=""; 
    for(int i=0; i<10; ++i) { 
    s+=c; 
    } 
    return s; 
} 

int main() { 
    cout << createString('a') << ' ' << createString('z') << endl; 
    return 0; 
} 

Z brzękiem ++ pisze on:

aaaaaaaaaa zzzzzzzzzz

jak chcę go mieć, ale z g ++ pisze on:

aaaaaaaaaa aaaaaaaaaa

Dlaczego tak jest? Czy standard implementacji g ++ jest zgodny? Co powinienem zrobić, jeśli chcę, aby funkcja zwróciła tymczasowy typ "duży" przez odniesienie, jak tutaj, aby uniknąć niepotrzebnej kopii?

dziękuję, jeśli możesz pomóc (i wybacz mi, jeśli moje pytanie nie jest jasne, angielski nie jest moim naturalnym językiem).

+3

Dlaczego Twój "ciąg" jest najważniejszy ?! – us2012

+0

Dla innych czytelników, Zwróć uwagę, że ciąg jest zwracany przez odniesienie. –

+0

być zwrotnym przez odniesienie, to musi być, nie? – user2174468

Odpowiedz

7

I co należy zrobić, jeśli chcę funkcja zwraca tymczasowy „duży” typ poprzez odniesienie podobnego tutaj, aby uniknąć niepotrzebnego kopię?

Nie będzie. RVO i NRVO mogą się tym zająć w prosty sposób. Ponadto przenieś semantykę. W skrócie, nic nie stoi na przeszkodzie, aby zwrócić wartość w ogóle.

22

Tak, obie implementacje są zgodne. The order of evaluation of function arguments is not specified.

Dlatego createString('a') i createString('z') można oceniać w dowolnej kolejności. Ponadto, createString('z') można ocenić przed lub po zapisaniu wyniku createString('a').

Ponieważ funkcja jest stanowa i zwraca stan przez odniesienie, oba wyjścia są dopuszczalne, podobnie jak zzzzzzzzzz zzzzzzzzzz.

Na koniec warto zauważyć, że posiadanie stanu static byłoby poważnym bólem głowy w środowisku wielowątkowym.

+3

Nie jest to kolejność 'createString ('a') 'i' createString ('z') ', ale raczej ich kolejność względem operatorów' << ', które powodują nieoczekiwane zachowanie. – Yakk

+3

Rzeczywiście. Kompilator może generować oba wywołania do 'createString()' przed wszelkimi wywołaniami do 'operatora <<()' (jak to najwyraźniej robi g ++) lub do ich przeplatania (jak robi to clang ++). Zatem jest to względna kolejność wszystkie te funkcje są ważne. –

+0

@Tak, ale ta kolejność nie jest określona. Wynik "aaaaaaaaa aaaaaaaaa" lub "zzzzzzzzzz aaaaaaaaa" byłby równie ważny. –

2

Co powinienem zrobić, jeśli chcę, aby funkcja zwróciła tymczasowy "duży" typ przez odniesienie, jak tutaj, aby uniknąć niepotrzebnej kopii?

Zadzwoń tylko raz na wyrażenie. Na przykład będzie to działało dobrze:

std::cout << createString('a') << ' '; 
std::cout << createString('z') << std::endl; 
Powiązane problemy