2016-07-25 11 views
6

Jestem nieco mylić o następującym kodu C++:Inicjacja statycznych const zmiennej

#include <iostream> 

using namespace std; 

void test(const string& str) 
{ 
    static const char * const c = str.c_str(); 
    cout << c << endl; 
} 

int main(int argc, char* argv[]) 
{ 
    test("Hello"); 
    test("Nooo"); 
    return 0; 
} 

Ponieważ zmienna c została zadeklarowana jako static i const, nie powinno to być inicjowane tylko raz i zachować jego wartość początkową aż proces się zakończy? Zgodnie z tym rozumowaniem, spodziewałem się następujący wynik:

Hello 
Hello 

Ale mam:

Hello 
Nooo 

Czy możesz wyjaśnić, dlaczego wartość zmiennej c została zmodyfikowana między dwoma wywołań funkcji, mimo to to jest zmienna const?

Odpowiedz

14

Twój program ma niezdefiniowane zachowanie .

Po przejechaniu "hello" do test tworzony jest tymczasowy std::string obiektu, a od tego łańcucha c jest zbudowany (co jest tylko wskaźnik do danych obiektu String).

Po zakończeniu wywołania funkcji tymczasowy obiekt std::string zostaje zniszczony, a c staje się zwisającym wskaźnikiem. Ponowne użycie to niezdefiniowane zachowanie.

W twoim przypadku drugie dane obiektu tymczasowego mają ten sam adres pamięci co pierwszy, więc c wskazuje na te dane. Nie jest to gwarantowane.

+0

W rzeczywistości nie jest niezdefiniowany. ** Dereferencing ** jest niezdefiniowany. Ponieważ ma zawsze poprawny adres po dereferencji, jest to poprawny program. – StoryTeller

+3

@StoryTeller, 'cout << c << endl;' robi dereferencję wskaźnika. –

+1

@StoryTeller Operator wyjściowy używa dereferencji. –

1

Masz niezdefiniowane zachowanie w kodzie, więc wyniki mogą się różnić. UB jest, ponieważ wywołanie test("Hello"); tworzy tymczasowy, który następnie przypisuje do statycznej zmiennej lokalnej. Ta tymczasowa jest zniszczona po zakończeniu połączenia, więc wskaźnik w funkcji testu jest zwisający. Jeśli go używasz, masz niezdefiniowane zachowanie.

Możliwe jest, że menedżer pamięci ponownie wykorzystuje ten sam obszar pamięci, aby w wynikach pojawiały się Witaj i Nie.

Powiązane problemy