2013-02-25 8 views
11

Lepiej zastąpićCzy zawsze, gdy to możliwe, należy zamienić "const int" na "constexpr int" w C++ 11?

const int one = 1; 
const int two = 2; 

z tym?

constexpr int one = 1; 
constexpr int two = 2; 

Czy dobrze rozumiem, że oba bloki są semantycznie identyczne i że jest to obecnie tylko kwestia gustu?

Z drugiej strony, jako constexpr oznacza const, można argumentować, że bardziej konsekwentnie jest zawsze preferować bardziej restrykcyjną formę, nawet w banalnych sytuacjach, w których nie ma to znaczenia?

(Rozumiem, że sytuacja całkowicie się zmienia, gdy wyrażenie po prawej stronie może być bardziej skomplikowane. W celu wyjaśnienia pytanie skupia się tylko na najbardziej prostym przypadku, w którym wyrażenie jest stałą liczbą całkowitą.)

+1

Jedyne, co mogę wymyślić, to jeśli określasz coś podobnego do API, możesz zdecydować się na użycie 'const int' do przechowywania stałego wyrażenia, ponieważ ta właściwość może nie być dostępna w przyszłych wersjach. – Pubby

Odpowiedz

13

Myślę, że oświadczenie mówiąc, że const i constexprsą semantycznie identyczne” powinna zostać zmieniona: obaj zadeklarować obiekty, których wartość nie może się zmienić, ale constexpr wymaga również ekspresję initializer być obliczalna w czasie kompilacji.

Teraz, jeśli wyrażenie po prawej stronie nie może być obliczone podczas kompilacji, używanie constexpr nie wchodzi w grę. Z drugiej strony, dopóki inicjalizator jest literałem, możesz może użyć constexpr, ale należy wziąć pod uwagę to, co semantyka twojej zmiennej jest: czy twoja stała zmienna naprawdę reprezentuje coś, którego wartość powinna być obliczana podczas kompilacji. czas?

W przypadku optyki konserwacji/ewolucji SW możliwe jest, że zmienisz sposób inicjalizacji zmiennej przez cały czas: dziś inicjator jest dosłowny, jutro może być bardziej złożonym wyrażeniem.

Bez względu na sposób, w jaki są przypisując mu wartość teraz, myślisz, że i kiedykolwiek muszą być zainicjowany przez cokolwiek innego niż dosłowne, i że wyrażenie inicjalizacji nie mogą być obliczalna w czasie kompilacji? Jeśli tak jest, to po prostu ustaw zmienną const, nawet jeśli obecnie zainicjalizujesz ją literalnie; w przeciwnym razie uczyń go constexpr.

Innymi słowy, wybierz kwalifikator, który najlepiej wyraża semantykę zmiennej.

+2

Chciałbym zmienić tę ostatnią radę na głowie: zadaj sobie pytanie: "Czy to nazwisko musi zostać rozwiązane w czasie kompilacji?" (np. Używam go jako rozmiaru tablicy lub wartości wyliczeniowej gdzieś.) Jeśli tak, użyj 'constexpr', aby nikt nie miał ochoty go zmieniać w sposób, który spowodowałby niepowodzenie użycia nazwy. – rici

+3

@rici: Ma sens, ale myślę, że OP dotyczy głównie przypadku, w którym odpowiedź na pytanie w komentarzu brzmi "nie". Kiedy odpowiedź brzmi "tak", z pewnością zmienną należy wprowadzić 'constexpr'. Ale co jeśli inicjalizator nie musi być stricte wyrażeniem "constexpr", a akurat teraz nim jest? Na to pytanie próbowałem odpowiedzieć. –

+0

Wystarczająco sprawiedliwe, ale wydaje mi się, że bardzo trudno jest odpowiedzieć na pytanie "czy może pewnego dnia zainicjować coś bardziej skomplikowanego niż dosłowne?", i bardzo łatwo odpowiedzieć na pytanie" Czy 'i' musi być znany w czasie kompilacji?" Używanie 'constexpr' konsekwentnie do wskazania tego ostatniego dostarcza użytecznych informacji do czytnika kodów, użycie' const' do wskazania, że ​​wyobrażasz sobie możliwa kontrowersyjna przyszłość, nie tak bardzo, – rici