J'ai une référence à MyOjbect
, mais l'objet exact dépend d'une condition. Je veux donc faire quelque chose comme ça:
MyObject& ref;
if([condition])
ref = MyObject([something])
else
ref = MyObject([something else]);
Je ne peux pas le faire pour le moment car le compilateur ne me permet pas de déclarer mais pas d'initialiser une référence. Que puis-je faire pour atteindre mon objectif ici?
Vous devez l'initialiser. Mais si vous souhaitez l'initialiser conditionnellement, vous pouvez faire quelque chose comme ceci:
MyObject& ref = (condition) ? MyObject([something]) : MyObject([something else]);
AFAIK cela ne peut pas être fait avec une référence. Vous devez utiliser un pointeur:
MyClass *ptr;
if (condition)
ptr = &object;
else
ptr = &other_object;
Le pointeur agira comme une référence. N'oubliez pas d'utiliser ->
pour l'accès des membres.
Tu ne peux pas faire ça. Les références doivent être liées à quelque chose, vous pouvez ne pas l'aimer mais cela empêche toute une classe d'erreurs, car si vous avez une référence, vous pouvez toujours supposer qu'elle est liée à quelque chose, contrairement à un pointeur qui pourrait être nul.
Votre exemple de code ne fonctionnerait pas de toute façon car vous essayez de lier une référence non const à un objet temporaire, qui n'est pas valide.
Pourquoi en avez-vous besoin de toute façon? Une solution serait de vous assurer que votre type a un constructeur par défaut peu coûteux et peut être déplacé efficacement, alors faites simplement:
MyObject obj;
if([condition])
obj = MyObject([something])
else
obj = MyObject([something else]);
Sinon, vous devrez mettre le code conditionnel dans une ou plusieurs fonctions, soit:
const MyObject& ref = createObject([condition]);
ou
const MyObject& ref = [condition] ? doSomething() : doSomethingElse();
Notez que ces deux versions utilisent une référence const , qui peut se lier à une valeur temporaire, si l'objet doit être non const, puis à nouveau arrêter d'essayer d'utiliser une référence:
MyObject obj = createObject([condition]);
Ce sera probablement aussi efficace que ce que vous essayez de faire, grâce à optimisation de la valeur de retour
En C++, vous ne pouvez pas déclarer une référence sans initialisation. Vous devez l'initialiser.
Réponse courte: non.
Réponse légèrement plus longue: faites quelque chose comme ceci:
MyObject& getObject()
{
if([condition])
return [something]
else
return [something else];
}
MyObject& ref = getObject();
Les exclusions habituelles concernant les références s'appliquent bien sûr.
Ce que j'aime faire, c'est un lambda qui est immédiatement exécuté.
Supposons que nous voulons un const std :: string & à une variable sous la carte - si la carte ne contient pas de clé donnée - nous voulons lancer.
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.
}
Vous pouvez également utiliser std :: invoke () pour le rendre plus lisible (depuis 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.
}
});
}
MyClass *ptr;
if (condition)
ptr = &object;
else
ptr = &other_object;
MyClass &ref = *ptr;
if ([condition]) MyObject & ref = MyObject ([quelque chose]); else MyObject & ref = MyObject ([autre chose]);