Ich habe einen Verweis auf MyOjbect
, aber das genaue Objekt hängt von einer Bedingung ab. Also möchte ich so etwas machen:
MyObject& ref;
if([condition])
ref = MyObject([something])
else
ref = MyObject([something else]);
Ich kann dies derzeit nicht tun, da der Compiler mir nicht erlaubt, eine Referenz zu deklarieren, aber nicht zu initialisieren. Was kann ich tun, um hier mein Ziel zu erreichen?
MyObject& ref = MyObject([something]);
Dies funktioniert auch ohne die Bedingung: nicht , da Sie eine temporäre Referenz nicht an eine nicht konstante Wertreferenz binden können.Antworten:
Sie müssen es initiieren. Wenn Sie es jedoch bedingt initialisieren möchten, können Sie Folgendes tun:
MyObject& ref = (condition) ? MyObject([something]) : MyObject([something else]);
quelle
AFAIK das kann nicht mit einer Referenz gemacht werden. Sie müssten einen Zeiger verwenden:
MyClass *ptr; if (condition) ptr = &object; else ptr = &other_object;
Der Zeiger verhält sich ähnlich wie eine Referenz. Vergessen Sie nicht,
->
für den Mitgliederzugriff zu verwenden .quelle
MyClass &ref = *ptr
ob Sie sie in eine Referenz verwandeln möchten ...new
).ptr
zeigt auf Objekte, die auf dem Stapel zugeordnet sind.Das kannst du nicht machen. Referenzen müssen an etwas gebunden sein, es mag Ihnen vielleicht nicht gefallen, aber es verhindert eine ganze Klasse von Fehlern, denn wenn Sie eine Referenz haben, können Sie immer davon ausgehen, dass sie an etwas gebunden ist, im Gegensatz zu einem Zeiger, der null sein könnte.
Ihr Beispielcode würde sowieso nicht funktionieren, da Sie versuchen, einen nicht konstanten Verweis an ein temporäres Objekt zu binden, das ungültig ist.
Warum brauchen Sie es überhaupt als Referenz? Eine Lösung wäre, sicherzustellen, dass Ihr Typ über einen kostengünstigen Standardkonstruktor verfügt und effizient verschoben werden kann. Führen Sie dann einfach Folgendes aus:
MyObject obj; if([condition]) obj = MyObject([something]) else obj = MyObject([something else]);
Andernfalls müssten Sie den bedingten Code in eine oder mehrere Funktionen einfügen:
const MyObject& ref = createObject([condition]);
oder
const MyObject& ref = [condition] ? doSomething() : doSomethingElse();
Beachten Sie, dass beide Versionen eine const- Referenz verwenden, die an eine temporäre Referenz gebunden werden kann. Wenn das Objekt nicht const sein muss, beenden Sie erneut den Versuch, eine Referenz zu verwenden:
Dies wird dank der Optimierung des Rückgabewerts wahrscheinlich genauso effizient sein wie das, was Sie versucht haben
quelle
In C ++ können Sie eine Referenz nicht ohne Initialisierung deklarieren. Sie müssen es initialisieren.
quelle
class test{ test(param o ):ref(o){}myobj& ref;}
Kurze Antwort: Sie nicht.
Etwas längere Antwort: Mach so etwas:
MyObject& getObject() { if([condition]) return [something] else return [something else]; } MyObject& ref = getObject();
Übliche Haftungsausschlüsse bezüglich Referenzen gelten selbstverständlich.
quelle
getObject()
eine Referenz zurückgegeben? Worauf bezieht es sich?Was ich gerne mache, ist ein Lambda, das sofort ausgeführt wird.
Nehmen wir an, wir wollen eine const std :: string & zu einer Variablen unter der Karte - wenn die Karte keinen bestimmten Schlüssel enthält - wollen wir werfen.
int main() { std::map<std::string, std::string> myMap = {{"key", "value"}}; const std::string& strRef = [&]()->const std::string& { try { return myMap.at("key"); // map::at might throw out_of_range } catch (...) { // handle it somehow and/or rethrow. } }(); // <- here we immediately call just created lambda. }
Sie können auch std :: invoke () verwenden , um die Lesbarkeit zu verbessern (seit C ++ 17).
int main() { std::map<std::string, std::string> myMap = {{"key", "value"}}; const std::string& strRef = std::invoke([&]()->const std::string& { try { return myMap.at("key"); // map::at might throw out_of_range } catch (...) { // handle it somehow and/or rethrow. } }); }
quelle
MyClass *ptr; if (condition) ptr = &object; else ptr = &other_object; MyClass &ref = *ptr;
quelle
MyClass &ref = *ptr;
am Ende vor, das hier die Schlüsselzeile ist, die später weitere Dereferenzen vermeidet, weiter kommentiert unter: stackoverflow.com/a/62793754/895245if ([Bedingung]) MyObject & ref = MyObject ([etwas]); sonst MyObject & ref = MyObject ([etwas anderes]);
quelle
Normalerweise mache ich das (C ++ 11 oder höher):
std::shared_ptr<ObjType> pObj; if(condition) pObj = std::make_shared<ObjType>(args_to_constructor_1); else pObj = std::make_shared<ObjType>(args_to_constructor_2);
Dies ist sauber und ermöglicht die Verwendung der Objektdefinition mit (möglicherweise unterschiedlichen) Konstruktionen. Dies können Sie nicht direkt mit Zeigern tun, da sich der Compiler über die Verwendung temporärer Objekte beschwert.
quelle
Sie können das Schlüsselwort "extern" verwenden: Zum ersten Mal (vorausgesetzt, in der Header-Datei) können Sie Ihre Variable vor der Deklaration mit dem Schlüsselwort "extern" deklarieren. Später (in der Quelldatei) wiederholen Sie die Deklaration ohne "extern" und weisen ihr einen Wert zu.
quelle