Gibt es einen Unterschied zwischen den folgenden Definitionen?const vs conexpr auf Variablen
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
Wenn nicht, welcher Stil wird in C++ 11 bevorzugt?
Gibt es einen Unterschied zwischen den folgenden Definitionen?const vs conexpr auf Variablen
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
Wenn nicht, welcher Stil wird in C++ 11 bevorzugt?
Ich glaube es gibt einen Unterschied. Lassen Sie uns sie umbenennen, so dass wir über sie leicht mehr sprechen kann:
const double PI1 = 3.141592653589793;
constexpr double PI2 = 3.141592653589793;
Sowohl PI1
und PI2
konstant sind, dh Sie können sie nicht ändern können. nurPI2
ist eine Kompilierzeitkonstante. Es wird soll initialisiert werden zu kompilierter Zeit. PI1
kann zur Kompilierzeit oder zur Laufzeit initialisiert werden. Außerdem kann nurPI2
in einem Kontext verwendet werden, der eine Kompilierzeitkonstante erfordert. Zum Beispiel:
constexpr double PI3 = PI1; // error
aber:
constexpr double PI3 = PI2; // ok
und:
static_assert(PI1 == 3.141592653589793, ""); // error
aber:
static_assert(PI2 == 3.141592653589793, ""); // ok
In Bezug auf die sollten Sie verwenden? Verwenden Sie, was immer Ihren Bedürfnissen entspricht. Möchten Sie sicherstellen, dass Sie über eine Kompilierzeitkonstante verfügen, die in Kontexten verwendet werden kann, in denen eine Kompilierzeitkonstante erforderlich ist? Möchten Sie in der Lage sein, es mit einer zur Laufzeit ausgeführten Berechnung zu initialisieren? Usw.
Sind Sie sicher? Weil const int N = 10; char a [N]; 'funktioniert, und Array-Grenzen müssen Kompilierzeitkonstanten sein. – fredoverflow
Ich bin sicher, soweit die Beispiele, die ich geschrieben habe, gehen (getestet jedes von ihnen vor dem Posten). Jedoch erlaubt mir mein Compiler, 'PI1' in eine Kompilierzeit-Integralkonstante zu konvertieren, die in einem Array verwendet wird, aber nicht als ein nicht-typischer integraler Template-Parameter. Die Kompilierbarkeit von 'PI1' in einen ganzzahligen Typ erscheint mir also ein wenig unpassend. –
@HowardHinnant: Die Regeln für die Konvertierung von lvalue-to-rvalue unterscheiden sich subtil für ganzzahlige und nicht ganzzahlige Typen: (5.19 (2)) 'ein glvalue des Integral- oder Enumerationstyps, der sich auf ein nichtflüchtiges const-Objekt mit einem vorhergehenden bezieht Initialisierung, initialisiert mit einem konstanten Ausdruck 'vs.' einem glvalue des Literaltyps, der auf ein nichtflüchtiges Objekt verweist, das mit conexpr definiert wurde, oder das sich auf ein Unterobjekt eines solchen Objekts bezieht. Das ist nicht das Gleiche wie die implizite Umwandlung in 'int', die unterschiedliche Regeln hat. – rici
Kein Unterschied hier, aber es spielt eine Rolle, wenn Sie einen Typ haben, der einen Konstruktor hat.
struct S {
constexpr S(int);
};
const S s0(0);
constexpr S s1(1);
s0
ist eine Konstante, aber es verspricht nicht zur Compile-Zeit initialisiert werden. s1
ist markiert constexpr
, so ist es eine Konstante und, weil S
's Konstruktor auch constexpr
markiert ist, wird es zur Kompilierzeit initialisiert werden.
Meistens zählt diese, wenn die Initialisierung zur Laufzeit zeitaufwendig sein würde, und Sie wollen, dass die Arbeit drücken auf die Compiler ab, wo es ist auch zeitaufwendig, aber langsam nicht die Ausführungszeit des kompilierten Programms nach unten
Ich bin damit einverstanden: die Schlussfolgerung ich angekommen war, dass 'constexpr' zu einer Diagnose führen sollte die Kompilierung -Zeitberechnung des Objekts unmöglich sein. Was weniger klar ist, ist, ob eine Funktion * erwartet * ein konstanter Parameter zur Kompilierzeit ausgeführt werden könnte, sollte der Parameter als 'const' und nicht als 'constexpr' deklariert werden, dh würde 'constexpr int foo (S)' ausgeführt werden zur Kompilierzeit, wenn ich 'foo (s0)' rufe? –
@MatthieuM: Ich bezweifle, ob 'foo (s0)' zur Kompilierzeit ausgeführt werden würde, aber man weiß nie: Ein Compiler darf solche Optimierungen durchführen. Sicher, weder gcc 4.7.2 noch clang 3.2 erlauben es mir, constexpr a = foo (s0) zu kompilieren. – rici
consExpr zeigt einen Wert an, der konstant ist und während der Kompilierung bekannt ist.
const zeigt einen Wert an, der nur konstant ist; Es ist nicht zwingend notwendig, dies während der Kompilierung zu wissen.
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
Beachten Sie, dass const nicht die gleiche Garantie wie constexpr bietet, weil const Objekte nicht mit den Werten während der Kompilierung bekannt initialisiert werden müssen.
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
Alle conexpr Objekte sind const, aber nicht alle const Objekte sind constexpr.
Wenn Sie möchten, dass Compiler garantieren, dass eine Variable einen Wert hat, der in Kontexten verwendet werden kann, die Kompilierzeitkonstanten erfordern, ist das Werkzeug, nach dem zu suchen, conexpr, nicht const.
Ich mochte Ihre Erklärung sehr .. können Sie bitte kommentieren mehr auf Wo sind die Fälle, die wir brauchen, um Kompilierzeit Konstanten in realen Szenarien zu verwenden. –
@MayukhSarkar Einfach Google _C++ warum constexpr_, z. http://stackoverflow.com/questions/4748083/when-should-you-use-constexpr-capability-in-c11 –
A consExpr symbolische Konstante muss einen Wert erhalten, der zur Kompilierzeit bekannt ist. Zum Beispiel:
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
// ...
}
Fälle zu behandeln, in denen der Wert einer „Variable“, die mit einem Wert initialisiert wird, der zum Zeitpunkt der Kompilierung nicht bekannt ist, aber ändert sich nie nach der Initialisierung C++ eine zweite Form von konstanten bietet (a const). Beispiel:
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
}
Solche „const Variablen“ sind aus zwei Gründen sehr häufig:
Vielleicht sollten Sie erwähnt haben, dass der Text in Ihrer Antwort wörtlich aus "Programmierung: Prinzipien und Praxis mit C++ "von Stroustrup – Aky
Superset: http://stackoverflow.com/questions/14116003/difference-between-constexpr-and-const –