Ich war nur schockiert, dass dies erlaubt ist:
if( int* x = new int( 20 ) )
{
std::cout << *x << "!\n";
// delete x;
}
else
{
std::cout << *x << "!!!\n";
// delete x;
}
// std:cout << *x; // error - x is not defined in this scope
Ist dies nach dem Standard zulässig oder handelt es sich nur um eine Compiler-Erweiterung?
PS Da es dazu mehrere Kommentare gab - ignorieren Sie bitte , dass dieses Beispiel "schlecht" oder gefährlich ist. Ich weiß was. Dies ist nur das erste, was mir als Beispiel in den Sinn kam.
c++
variables
if-statement
standards
Kiril Kirov
quelle
quelle
C
? Du meinst, dass dies dort nicht erlaubt ist und das hat mich vielleicht denken lassen, dass es in C ++ nicht erlaubt ist?new (std::nothrow)
Version - andernfalls wird Ihr Beispielelse
aufgrund einesstd::bad_alloc
Zuordnungsfehlers niemals aufgerufen.Antworten:
Dies ist in der Spezifikation seit C ++ 98 zulässig.
Aus Abschnitt 6.4 "Auswahlanweisungen":
Das folgende Beispiel stammt aus demselben Abschnitt:
if (int x = f()) { int x; // ill-formed, redeclaration of x } else { int x; // ill-formed, redeclaration of x }
quelle
else
. Irgendwie dachte ich immer, es wäre nur in derif
Sektion verfügbar ...Keine wirkliche Antwort (aber Kommentare eignen sich nicht gut für Codebeispiele), eher ein Grund, warum es unglaublich praktisch ist:
if (int* x = f()) { std::cout << *x << "\n"; }
Immer wenn eine API einen "Optionstyp" zurückgibt (für den zufällig auch eine boolesche Konvertierung verfügbar ist), kann dieser Konstrukttyp genutzt werden, sodass auf die Variable nur in einem Kontext zugegriffen werden kann, in dem es sinnvoll ist, ihren Wert zu verwenden. Es ist eine wirklich mächtige Redewendung.
quelle
boost::optional
) mögen und einen "Sentinel" -Wert haben, um das Fehlen eines echten Werts anzuzeigen . Wenn sie auch eine Konvertierung in bool bereitstellen, deren Wert ausschließlich vom Vorhandensein / Fehlen eines im Typ enthaltenen realen Werts abhängt, funktioniert die Redewendung. Zum Beispiel:if (boost::optional<int> x = f()) { std::cout << *x << '\n'; }
funktioniert auch.Es ist Standard, auch in der alten C ++ 98-Version der Sprache:
quelle
Definition einer Variablen in dem bedingten Teil einer
while
,if
undswitch
Aussage ist Standard. Die relevante Klausel ist 6.4 [stmt.select] Absatz 1, der die Syntax für die Bedingung definiert.Übrigens ist Ihre Verwendung sinnlos: Wenn dies
new
fehlschlägt, wird einestd::bad_alloc
Ausnahme ausgelöst .quelle
Hier ist ein Beispiel, das die nicht typische Verwendung einer in einer if- Bedingung deklarierten Variablen demonstriert .
Der Variablentyp ist
int &
sowohl in Boolesche konvertierbar als auch in den Zweigen then und else verwendbar .#include <string> #include <map> #include <vector> using namespace std; vector<string> names {"john", "john", "jack", "john", "jack"}; names.push_back("bill"); // without this push_back, my g++ generated exe fails :-( map<string, int> ages; int babies = 0; for (const auto & name : names) { if (int & age = ages[name]) { cout << name << " is already " << age++ << " year-old" << endl; } else { cout << name << " was just born as baby #" << ++babies << endl; ++age; } }
Ausgabe ist
john was just born as baby #1 john is already 1 year-old jack was just born as baby #2 john is already 2 year-old jack is already 1 year-old bill was just born as baby #3
Leider kann die Variable in der Bedingung nur mit der Deklarationssyntax '=' deklariert werden.
Dies schließt andere möglicherweise nützliche Fälle von Typen mit einem expliziten Konstruktor aus.
Zum Beispiel wird das nächste Beispiel mit einem
std::ifstream
nicht kompiliert ...if (std::ifstream is ("c:/tmp/input1.txt")) { // won't compile! std::cout << "true: " << is.rdbuf(); } else { is.open("c:/tmp/input2.txt"); std::cout << "false: " << is.rdbuf(); }
Bearbeitet Januar 2019 ... Sie können jetzt emulieren, was ich erklärt habe, konnte nicht getan werden ...
Dies funktioniert für bewegliche Klassen wie ifstream in C ++ 11 und sogar für nicht kopierbare Klassen seit C ++ 17 mit Kopierelision.
Bearbeitet im Mai 2019: Verwenden Sie auto, um die Ausführlichkeit zu verringern
{ if (auto is = std::ifstream ("missing.txt")) { // ok now ! std::cout << "true: " << is.rdbuf(); } else { is.open("main.cpp"); std::cout << "false: " << is.rdbuf(); } } struct NoCpy { int i; int j; NoCpy(int ii = 0, int jj = 0) : i (ii), j (jj) {} NoCpy(NoCpy&) = delete; NoCpy(NoCpy&&) = delete; operator bool() const {return i == j;} friend std::ostream & operator << (std::ostream & os, const NoCpy & x) { return os << "(" << x.i << ", " << x.j << ")"; } }; { auto x = NoCpy(); // ok compiles // auto y = x; // does not compile if (auto nocpy = NoCpy (7, 8)) { std::cout << "true: " << nocpy << std::endl; } else { std::cout << "false: " << nocpy << std::endl; } }
quelle