const vs constexpr na zmiennych
Czy istnieje różnica między następującymi definicjami?
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
Jeśli nie, jaki styl jest preferowany w C++11?
4 answers
Wierzę, że jest różnica. Zmienimy ich nazwy, abyśmy mogli łatwiej o nich rozmawiać:
const double PI1 = 3.141592653589793;
constexpr double PI2 = 3.141592653589793;
Zarówno PI1
jak i PI2
są stałe, co oznacza, że nie można ich modyfikować. Jednakże tylko PI2
jest stałą czasu kompilacji. To powinno być zainicjowane w czasie kompilacji. PI1
może być inicjowany w czasie kompilacji lub uruchomienia. Ponadto tylko PI2
może być używany w kontekście wymagającym stałej czasu kompilacji. Na przykład:
constexpr double PI3 = PI1; // error
Ale:
constexpr double PI3 = PI2; // ok
I:
static_assert(PI1 == 3.141592653589793, ""); // error
Ale:
static_assert(PI2 == 3.141592653589793, ""); // ok
Do czego należy użyć? Użyj tego, co spełni Twoje potrzeby. Czy chcesz mieć pewność, że masz stałą czasu kompilacji, która może być używana w kontekstach, w których wymagana jest stała czasu kompilacji? Czy chcesz być w stanie zainicjować go z obliczeń wykonanych w czasie wykonywania? Itd.
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-04-05 00:32:05
Tutaj nie ma różnicy, ale to ma znaczenie, gdy masz typ, który ma konstruktor.
struct S {
constexpr S(int);
};
const S s0(0);
constexpr S s1(1);
s0
jest stałą, ale nie obiecuje być inicjalizowana w czasie kompilacji. s1
jest oznaczona constexpr
, więc jest stała, a ponieważ konstruktor S
jest również oznaczony constexpr
, zostanie zainicjowany w czasie kompilacji.
Głównie ma to znaczenie, gdy inicjalizacja w czasie wykonywania będzie czasochłonna i chcesz przenieść tę pracę na kompilator, gdzie jest to również czasochłonne, ale nie spowalnia czasu wykonania skompilowanego programu
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
2012-11-12 16:04:41
Constexpr wskazuje wartość, która jest stała i znana podczas kompilacji.
const wskazuje wartość, która jest tylko stała; nie jest obowiązkowe, aby wiedzieć podczas kompilacji.
int sz;
constexpr auto arraySize1 = sz; // error! sz's value unknown at compilation
std::array<int, sz> data1; // error! same problem
constexpr auto arraySize2 = 10; // fine, 10 is a compile-time constant
std::array<int, arraySize2> data2; // fine, arraySize2 is constexpr
Zauważ, że const nie oferuje tej samej gwarancji co constexpr, ponieważ const obiekty nie muszą być inicjowane wartościami znanymi podczas kompilacji.
int sz;
const auto arraySize = sz; // fine, arraySize is const copy of sz
std::array<int, arraySize> data; // error! arraySize's value unknown at compilation
Wszystkie obiekty constexpr są const, ale nie wszystkie obiekty const są constexpr.
Jeśli chcesz, aby Kompilatory zagwarantować, że zmienna ma wartość, która może być używane w kontekstach wymagających stałych w czasie kompilacji, narzędziem do sięgnięcia jest constexpr, a nie const.
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
2017-06-17 10:36:41
A constexpr symboliczna stała musi mieć wartość znaną w czasie kompilacji. Na przykład:
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
constexpr int c2 = n+7; // Error: we don’t know the value of c2
// ...
}
Do obsługi przypadków, w których wartość "zmiennej", która jest inicjalizowana wartością, która nie jest znana w czasie kompilacji, ale nigdy nie zmienia się po inicjalizacji, C++ oferuje drugą formę stałej (a const ). Na Przykład:
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
const int c2 = n+7; // OK, but don’t try to change the value of c2
// ...
c2 = 7; // error: c2 is a const
}
Takie "const zmienne " są bardzo powszechne z dwóch powodów:
- C++98 nie miał constexpr, więc ludzie używali const .
- Lista pozycji "zmienne", które nie są wyrażeniami stałymi (ich wartość nie jest znana w czasie kompilacji), ale nie zmieniają wartości po inicjalizacja sama w sobie jest bardzo przydatna.
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-03-28 01:09:53