Czy statyczna zmienna constexpr ma sens?

Jeśli mam zmienną wewnątrz funkcji (powiedzmy, dużą tablicę), czy ma sens deklarowanie jej zarówno static, jak i constexpr? constexpr gwarantuje, że tablica zostanie utworzona w czasie kompilacji, więc {[1] } będzie bezużyteczna?

void f() {
    static constexpr int x [] = {
        // a few thousand elements
    };
    // do something with the array
}

Czy static rzeczywiście robi tam coś pod względem generowanego kodu lub semantyki?

Author: David Stone, 2012-12-13

1 answers

Krótka odpowiedź jest taka, że nie tylko jest static przydatna, ale jest całkiem dobrze, że zawsze będzie pożądana.

Po pierwsze, zauważ, że static i constexpr są od siebie całkowicie niezależne. static określa czas życia obiektu podczas wykonywania; constexpr Określa, że obiekt powinien być dostępny podczas kompilacji. Kompilacja i wykonanie są rozbieżne i sprzeczne, zarówno w czasie, jak i przestrzeni. Więc po skompilowaniu programu constexpr nie jest już istotne.

Każda zmienna deklarowane {[2] } jest w domyśle const, Ale const i static są prawie ortogonalne (z wyjątkiem interakcji z static const liczbami całkowitymi.)

Model obiektowy C++ (§1.9) wymaga, aby wszystkie obiekty inne niż pola bitowe zajmowały co najmniej jeden bajt pamięci i miały adresy; ponadto wszystkie takie obiekty obserwowalne w programie w danym momencie muszą mieć odrębne adresy (paragraf 6). Nie wymaga to od kompilatora tworzenia nowej tablicy na stosie dla każdego wywołania funkcja z lokalną, niestatyczną tablicą const, ponieważ kompilator może przyjąć zasadę as-if pod warunkiem, że udowodni, że nie można zaobserwować żadnego innego takiego obiektu.

To nie będzie łatwe do udowodnienia, niestety, chyba że funkcja jest trywialna (na przykład, nie wywołuje żadnej innej funkcji, której ciało nie jest widoczne w jednostce tłumaczenia), ponieważ tablice, mniej lub bardziej z definicji, są adresami. Tak więc w większości przypadków tablica niestatyczna {[13] } będzie musiała być odtwarzane na stosie przy każdym wywołaniu, co pokonuje punkt możliwości obliczenia go w czasie kompilacji.

Z drugiej strony, lokalny obiekt static const jest współdzielony przez wszystkich obserwatorów, a ponadto może być zainicjalizowany, nawet jeśli funkcja, w której jest zdefiniowana, nigdy nie zostanie wywołana. Tak więc żadne z powyższych nie ma zastosowania, a kompilator może generować nie tylko pojedynczą jego instancję; może generować pojedynczą jego instancję w pamięci tylko do odczytu.

Więc zdecydowanie powinieneś użyj static constexpr w swoim przykładzie.

Jest jednak jeden przypadek, w którym nie chciałbyś użyć static constexpr. Jeśli constexpr zadeklarowany obiekt nie jest ODR-used lub zadeklarowany static, kompilator może go w ogóle nie dołączać. Jest to bardzo przydatne, ponieważ pozwala na użycie tymczasowych tablic constexpr w czasie kompilacji bez zanieczyszczania skompilowanego programu niepotrzebnymi bajtami. W takim przypadku zdecydowanie nie chcesz używać static, ponieważ static może wymusić istnienie obiektu w runtime.

 148
Author: rici,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-08 11:36:59