Temporäre Objekte in C++ (Temporäre Objekte in C++), Lektion, Seite 721427
https://www.purl.org/stefan_ram/pub/temporaere_objekte_c++ (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C++-Kurs

Explizite Typwandlungen in Funktionsschreibweise in C++ 

Manchmal hat ein Wert eines fundamentalen Typs, wie der durch ein Literal gegebene Ausdruck »5« oder der durch eine Summe gegebene Wert »5 + 2« keinen Namen und belegt zur Laufzeit eines Programms auch nicht unbedingt Speicherplatz.

Es ist möglich auch Ausdrücke für Exemplare ohne  eine Definition einer Variablen anzugeben. Solche Exemplare haben dann als keinen Namen. Sie werden auch nicht dauerhaft gespeichert, sondern nur solange wie sie erkennbar benötigt  werden.

Solche Exemplare werden auch temporär oder Temporär genannt.

Solche Exemplare können durch eine explizite Typkonvertierung in Funktionsschreibweise  (explicit type conversion (functional notation) ) oder als Wert anderer Ausdrücke entstehen. Ihre Lebenszeit endet normalerweise mit der Auswertung des sie enthaltenden Ausdrucks.

Das folgende Programmbeispiel zeigt die explizite Typkonvertierung in Funktionsschreibweise bei einem fundamentalen und bei einem benutzerdefiniertem Typ.

main.cpp

#include <iostream> /* ::std::cout */
#include <ostream> /* << */
#include <string> /* ::std::string */

#include <initializer_list>

int main()
{ ::std::cout << '>' << int() << "<\n";
::std::cout << '>' << int{} << "<\n";

::std::cout << '>' << int( 2 )<< "<\n";
::std::cout << '>' << int{ 2 }<< "<\n";

::std::cout << '>' << ::std::string() << "<\n";
::std::cout << '>' << ::std::string{} << "<\n";

::std::cout << '>' << ::std::string( "abc" )<< "<\n";
::std::cout << '>' << ::std::string{ "abc" }<< "<\n";

::std::cout << '>' << ::std::string( 65, 'A' )<< "<\n";
::std::cout << '>' << ::std::string{ 65, 'A' }<< "<\n"; }

::std::cout

>0<
>0<

>2<
>2<

><
><

>abc<
>abc<

>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA<
>AA<

Die Lebensdauer der in dem obenstehendem Programm erzeugten temporären Objekte endet jeweils mit der Auswertung der sie enthaltenden Ausgabeausdrücke.

Bei leeren Klammern wird in der Regel eine Wertinitialisierung durchgeführt. Bei einer Variablendefinition kann es vorkommen, daß leere runde Klammern dazu führen, daß diese nicht wie beabsichtigt verstanden wird. Bei der oben gezeigten explizite Typkonvertierung in Funktionsschreibweise mit leeren Klammern besteht dieses Risiko nicht. Die runden leeren Klammern haben dieselbe Bedeutung wie geschweifte leere Klammern, in beiden Fällen erfolgt eine Wertinitialisierung.

Falls die Klammern nur einen Ausdruck enthalten, so wird eine Typkonversion wie bei einem cast-Ausdruck durchgeführt.

Falls mehrere Ausdrücke in runden Klammern verwendet werden, so wird eine direkte Initialisierung durchgeführt, deren Bedeutung der Dokumentation der Klasse entnommen werden kann.

Falls mehrere Ausdrücke in geschweiften Klammern verwendet werden, so wird eine direkte Initialisierung mit Initialisierungsliste durchgeführt, deren Bedeutung der Dokumentation der Klasse entnommen werden kann.

An einigen Stellen ist eine implizite Typkonversion nicht erlaubt. In entsprechenden Fällen kann es dann helfen, eine explizite Typkonversion, wie sie gerade erklärt wurde, einzusetzen.

Typnamen aus mehreren  lexikalischen Einheiten

Bei Typnamen aus mehreren  lexikalischen Einheiten kann die Funktionsschreibweise nicht  verwendet werden.

main.cpp

#include <iostream> /* ::std::cout */
#include <ostream> /* << */

#include <initializer_list>

int main()
{ ::std::cout << '>' << unsigned int( 2 )<< "<\n"; }

Protokoll
error: expected primary-expression before 'unsigned'
| { ::std::cout << '>' << unsigned int( 2 )<< "<\n"; }
| ^~~~~~~~

Temporäre Objekte in Definitionen

Das folgende Programmbeispiel zeigt die explizite Typkonvertierung in Funktionsschreibweise mit nachfolgender Kopie des Wertes in eine Variable mit Blocklebensdauer. Der Wert (Zustand des Objekts) bleibt in diesem Falle erhalten, weil er in ein anderes Objekt mit längerer Lebensdauer kopiert  wird, während das zunächst erzeugte temporäre Objekt nur während der Ausführung der Definition existiert.

main.cpp

#include <iostream> /* ::std::cout */
#include <ostream> /* << */
#include <string> /* ::std::string */

int main()
{ ::std::string const s = ::std::string( "abc" );
::std::cout << s << '\n'; }

::std::cout
abc

Typumformungen in Funktionsschreibweise in C++ 

(Andere Variante derselbe Lektion!)

C++ -draft von 2014
n4296
5.2.3 Explicit type conversion (functional notation) [expr.type.conv]
main.cpp

#include <iostream>
#include <ostream>

int main()
{ ::std::cout << int( 2 )<< '\n';
::std::cout << int() << '\n';
::std::cout << int{ 2 }<< '\n';
::std::cout << int{} << '\n';

::std::cout << ::std::string( "abc" )<< '\n';
::std::cout << ::std::string() << '\n';
::std::cout << ::std::string{ "abc" }<< '\n';
::std::cout << ::std::string{} << '\n'; }

::std::cout

2

0

2

0

abc

abc

.In dem folgenden Zitat steht »a« nicht nur für einen einzelnen Ausdruck, sondern kann auch für eine Liste von Ausdrücken stehen!

Zitat

The initialization that occurs in the forms
T x(a);
T x{a};
as well as in new expressions (5.3.4), static_cast expressions (5.2.9), functional notation type conversions
(5.2.3), mem-initializers (12.6.2), and the braced-init-list form of a condition is called direct-initialization.

Beispiel

Getrennte Erzeugung

main.cpp

#include <algorithm>
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <string>
#include <vector>

int main()

{ { ::std::vector< ::std::pair< int, int >>v;
::std::pair< int, int > const p{ 4, 5 };
::std::pair< int, int > const q{ 6, 7 };
v.push_back( p );
v.push_back( q );
::std::cout << v.at( 0 ).first << '\n';
::std::cout << v.at( 0 ).second << '\n';
::std::cout << v.at( 1 ).first << '\n';
::std::cout << v.at( 1 ).second << '\n'; } }

Protokoll
4
5
6
7

Erzeugung in Funktionsschreibweise, es ist nun einfacher noch ein weiteres Paar hinzuzufügen (allerdings wäre hier emplace_back noch besser)

main.cpp

#include <algorithm>
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <string>
#include <vector>

int main()

{ { ::std::vector< ::std::pair< int, int >>v;
v.push_back( ::std::pair < int, int >{ 4, 5 });
v.push_back( ::std::pair < int, int >{ 6, 7 });
::std::cout << v.at( 0 ).first << '\n';
::std::cout << v.at( 0 ).second << '\n';
::std::cout << v.at( 1 ).first << '\n';
::std::cout << v.at( 1 ).second << '\n'; } }

Protokoll
4
5
6
7

Beispiel

main.cpp

#include <iostream>
#include <ostream>
#include <random>

int main()
{ ::std::cout << ::std::random_device{}.entropy() << "\n"; }

0

Beispiel

Unten wird keine Variable a, sondern eine Funktion "std::atomic<int> a(int (*)())" deklariert

main.cpp

#include <iostream> /* ::std::cout */
#include <ostream> /* << */
#include <atomic> /* ::std::atomic */
#include <initializer_list>

int main()
{ ::std::atomic<int> a( int() ); ::std::cout << a << '\n'; }

transcript
1
F:\r\j\autocomp\main.cpp:9:18: warning: implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension [clang-diagnostic-microsoft-cast]

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram721427 stefan_ram:721427 Temporäre Objekte in C++ Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd721427, slrprddef721427, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/temporaere_objekte_c++