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?

Author: fredoverflow, 2012-11-12

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.

 237
Author: Howard Hinnant,
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

 64
Author: Pete Becker,
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.

 28
Author: Ajay yadav,
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:

  1. C++98 nie miał constexpr, więc ludzie używali const .
  2. 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.
"Programowanie: zasady i praktyka korzystania z C++" by Stroustrup
 10
Author: Jnana,
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