2017-07-28 42 views
8

Rozważmy następujący kod:Zwracanie łańcucha C w funkcji constexpr: dlaczego nie ma ostrzeżenia od kompilatora?

constexpr auto f() 
{ 
    auto str = "Hello World!"; 
    return str; 
} 

int main(int argc, char* argv[]) 
{ 
    static constexpr auto str = f(); 
    std::cout << str << std::endl; 
    return 0; 
} 

Czy to normalne, że mój kompilator nie wyświetla żadnego ostrzeżenia? Czy jest to określone zachowanie? Czy mam gwarancję, że program wyświetli "Hello World!"? Spodziewam się, że "Hello World!" nie będzie żyć poza zakresem funkcji ...

Odpowiedz

13

W C++ string literals ma static storage duration i działa tak długo, jak długo program działa. Zatem wskaźnik do literału ciągu znaków zwrócony z f jest zawsze ważny. Brak alokacji lub dealokacji.

Należy pamiętać, że literały ciągów mają typ const char[N], który w twoim przypadku zanika do const char * z powodu odliczenia typu auto. Jeśli zamiarem było wykorzystanie std::string można bezpośrednio skonstruować go

auto str = std::string("Hello World!"); 

lub użyj operator""s:

using std::string_literals; 
auto str = "Hello World!"s; 

Jednak od std::string nie jest typem dosłowny, to wartości cannot be constexpr więcej.

+1

"Literały ciągów mają typ" const char * "" Nie robią tego. –

+0

@ T.C. tablica 'const char' o konkretnej długości? – Orient

+0

@ T.C. Rzeczywiście, dziękuję. – lisyarus

5

Drugi efekt to z auto. To, co myślisz, nie zawsze jest tym, co decyduje kompilator. Może to prowadzić do niepoprawnego oczekiwania programisty - reguła jest tutaj kompilator zawsze wygrywa.

Faktem jest, że str jest na czas ciągły (czas przechowywania statycznego). Może być w pełni określony w czasie kompilacji, więc jest poprawnym constexpr.