CPP2019SSF04: Unterschied zwischen den Versionen

Aus Verteilte Systeme - Wiki
Wechseln zu: Navigation, Suche
K (Code-Beispiele)
K
Zeile 37: Zeile 37:
 
* Eine Funktion, die mit <code>constexpr</code> definiert wird, sagt nicht, dass sie einen ''const''-Wert zurückgibt.
 
* Eine Funktion, die mit <code>constexpr</code> definiert wird, sagt nicht, dass sie einen ''const''-Wert zurückgibt.
 
* Nur wenn die Funktionsparameter zur ''compile-time'' bekannt sind, wird sie auch zu dieser berechnet. Ansonsten handelt es sich dabei um eine ''normale'' Funktion, die zur ''run-time'' ausgeführt wird und nur in einem solchen Kontext verwendet werden kann. Dies stellt natürlich keinen Nachteil dar; im Gegenteil sind <code>constexpr</code>-Funktionen <q>universeller</q> einsetzbar. Es sei lediglich an dieser Stelle darauf hingewiesen.
 
* Nur wenn die Funktionsparameter zur ''compile-time'' bekannt sind, wird sie auch zu dieser berechnet. Ansonsten handelt es sich dabei um eine ''normale'' Funktion, die zur ''run-time'' ausgeführt wird und nur in einem solchen Kontext verwendet werden kann. Dies stellt natürlich keinen Nachteil dar; im Gegenteil sind <code>constexpr</code>-Funktionen <q>universeller</q> einsetzbar. Es sei lediglich an dieser Stelle darauf hingewiesen.
 
 
* Bei den Parametern sowie dem Return-Wert muss es sich um [https://en.cppreference.com/w/cpp/named_req/LiteralType ''LiteralTypes''] handeln
 
* Bei den Parametern sowie dem Return-Wert muss es sich um [https://en.cppreference.com/w/cpp/named_req/LiteralType ''LiteralTypes''] handeln
  +
* Ein ''constexpr''- Pointer ist ein ''const''- Pointer und kann sowohl auf ''const''- Objekte, als auch auf <q>non-''const''</q>- Objekte zeigen. Ungeachtet des Typs, muss es sich dabei um statische Objekte, explizit als <code>static</code>, oder implizit als global definiert, handeln.
   
 
=== Code-Beispiele ===
 
=== Code-Beispiele ===
Zeile 62: Zeile 62:
   
   
  +
static const int baz = 23; // baz wird zur compile/link time eine Adresse zugewiesen
 
  +
constexpr const int* cx_ptr = &baz; // constexpr-Pointer (const) auf const int
   
 
</source>
 
</source>

Version vom 14. Juli 2019, 17:08 Uhr

Feature: constexpr

  • Eingeführt in: C++ 11

Syntax

constexpr int foo = 42;
constexpr int baz() { return 42; }

Use Cases

Objekte, die als constexpr definiert wurden sind implizit const und besitzen Werte die bereits zur compile time bekannt sind. Letzteres wird dabei vom Compiler sichergestellt. Diese Eigenschaft unterscheidet sie von Objekten die lediglich als const deklariert wurden. Deren Wert einmal initialisiert, zwar nicht mehr verändert, aber unter Umständen erst zur run-time bekannt werden kann. Der Compiler prüft bei const nicht, ob das Objekt bereits zur compile time initialisiert wurde. Besonders bei umfangreichen Softwareprojekten bietet hier constexpr durch die Überprüfung des Compilers eine größere Sicherheit. Ein Objekt, dessen Wert bereits zur compile-time bekannt ist, kann überall dort verwendet werden, wo C++ eine constant expression fordert, wie z.B. bei Array-Größenangaben, Template-Argumenten etc.


Das Ergebnis einer Funktion, die als constexpr deklariert wurde, kann zur compile time berechnet werden, vorausgesetzt, die übergebenen Parameter sind ebenfalls zur compile time bekannt. Daher können auch sie im Kontext einer constant expression verwendet werden. Eine solche Funktion kann z.B. in allen möglichen Situationen verwendet werden, die bisher Makros erfordert hätten.


Die gennanten Eigenschaften machen constexpr auch besonders im Bereich der Embedded Systems interessant.

Motivation für die Einführung

Die Möglichkeit, dass Berechnungen bereits zur compile-time ausgeführt werden können, macht die Ausführung des Programms an sich schneller, obgleich sich die Zeit zum Kompilieren dabei verlängern kann. Auch können Fehler, die bereits bei der Kompilierung enstehen frühzeitig erkannt werden und müssen nicht mehr während der Ausführung behandelt werden.

Vorherige Lösungsansätze

Ein Ansatz, Berechnungen in die compile-time zu verlagern, besteht im sogenannten Template Metaprogramming. Dabei wird mithilfe von Templates Code bereits beim Kompilieren ausgeführt. Programme, die diese Technik verwenden können jedoch sehr unleserlich und schwer zu verstehen sein, daher stellt constexpr eine wesentliche Verbesserung dar.

Warnhinweise

  • Eine Funktion, die mit constexpr definiert wird, sagt nicht, dass sie einen const-Wert zurückgibt.
  • Nur wenn die Funktionsparameter zur compile-time bekannt sind, wird sie auch zu dieser berechnet. Ansonsten handelt es sich dabei um eine normale Funktion, die zur run-time ausgeführt wird und nur in einem solchen Kontext verwendet werden kann. Dies stellt natürlich keinen Nachteil dar; im Gegenteil sind constexpr-Funktionen universeller einsetzbar. Es sei lediglich an dieser Stelle darauf hingewiesen.
  • Bei den Parametern sowie dem Return-Wert muss es sich um LiteralTypes handeln
  • Ein constexpr- Pointer ist ein const- Pointer und kann sowohl auf const- Objekte, als auch auf non-const- Objekte zeigen. Ungeachtet des Typs, muss es sich dabei um statische Objekte, explizit als static, oder implizit als global definiert, handeln.

Code-Beispiele

// C++11 konforme, rekursive Berechnung der Fakultät einer natürlichen Zahl
constexpr uint32_t fac(uint32_t n) {
    return ( (1 == n) || (0 == n) ) ? 1 : ( n * fac(n - 1) );
}


// Iterative Berechnung der Fakultät einer natürlichen Zahl, ab C++14
constexpr uint32_t fac(uint32_t n) {
    uint32_t ret = 1;
    for (uint32_t i = 1; i < n; ++i)
        ret += ret*i;
    return ret;
}

// Compile-time check!
constexpr int size = 4;
constexpr char foo[size] = "foo";
static_assert(foo[3] == '\0', "Error");


static const int baz = 23;          // baz wird zur compile/link time eine Adresse zugewiesen
constexpr const int* cx_ptr = &baz; // constexpr-Pointer (const) auf const int