0
votes

Retour STD :: String via Opérateur ternaire - Retour à la poubelle

J'ai le code suivant:

Name is "�
          @"
pName is "Ternary Return Test"


2 commentaires

Si vous venez de retourner * pname (pas de terne), tout va bien?


Si vous n'obtenez pas un avertissement de compilation à ce sujet, augmentez votre niveau d'avertissement.


4 Réponses :


4
votes

Mais ce n'est pas le cas - je retourne une référence à une valeur non temporaire, qui devrait être parfaitement valide.

Vous seriez, mais vous n'avez plus de valeur non temporaire. [EXPR.COND] /4.3 a

Si E2 est une pr devalue ou si aucune des séquences de conversion ci-dessus peut être formée et au moins un des opérandes a (éventuellement qualifié de CV) de type de classe:

  • Si T1 et T2 sont le même type de classe (ignorant la qualification CV) et T2 est au moins comme CV-qualifié que T1, le type cible est T2,

    Et ce que cela se résume à ce que le troisième opérande est une pr devalue, toute l'expression est une pr devalue qui signifie que vous avez toujours un comportement indéfini lorsque vous retournez toujours une référence à une référence temporaire.


0 commentaires

3
votes

Type d'opérateur ternaire pour

pname? * PNAME: "(Sans nom)" est std :: string (nous avons std :: string & et const char * )

donc il est équivalent à pname? std :: string {* pname}: std :: string {"(Sans nom)"} .

Donc, vous renvoyez la référence de la variable temporaire ( dans les deux cas ) (Et ainsi de référence pendling, conduisant à UB lorsque vous l'utilisez).

Si vous avez utilisé si au lieu de ternaire, vous auriez votre erreur attendue < PRE> XXX

Une solution peut être; xxx

de sorte que les deux côtés sont de lvalue et le type commun est maintenant const std :: string & ( std :: string & et const std :: string & ).


0 commentaires

1
votes

Comme Yksisarvinen souligne, le problème est un problème de vie. "(Sans nom)" a une durée de stockage statique, mais ce n'est pas ce que vous revenez. Vous revenez std :: string {"(Sans nom)"} et une référence à être exact. Cette temporaire sans nom disparaît avant même que la fonction revienne même.

correction: xxx


5 commentaires

Et le problème est également avec * pname qui se transforme également en std :: string {* pname} parce que l'opérateur ternaire.


@ Jarod42: Pourquoi? * pname et defaultValue sont du même type, et les deux sont des glvalues. Ceci est équivalent à * (pname? Pname: & DefaultValue) .


@walnut: Yeah, "Sans nom" peut être utilisé pour initialiser un consexpr défaut mais qui n'a pas résolu le problème réel. Vous avez besoin d'un static const std STD :: chaîne .


@walnut: Pas assez de café pour un lundi: |


J'ai parlé de l'affaire OP, pas la solution fixe. Nous pourrions lire votre explication comme un problème est uniquement lorsque vous renvoyez "(Sans nom)" mais de l'autre côté comme un problème similaire.



0
votes

Pour référence (la référence de référence en suspens est déjà décrite déjà), cela devrait probablement être quelque chose comme xxx


3 commentaires

Désolé, mais ce dernier commentaire n'a pas de sens. Quelle serait la mauvaise branche? * pname lorsque pName == nullptr ? C'est sûr, par intention. * pname est séquencé - après le test de pname .


Si vous renvoyez une référence à temporaire est UB, alors une branche serait , même si elle n'est jamais exécutée - est problématique. Je vais devoir penser à une meilleure façon de l'exprimer.


@ Inutile ce n'est pas correct. Vous êtes autorisé à avoir UB dans une branche tant qu'elle n'est jamais exécutée. Le compilateur doit toujours assurer qu'un programme qui ne prend jamais la branche UB s'exécute avec le comportement défini.