getString()
restituire una copia di str
(getString()
restituisce per valore);
È giusto.
in tal modo, la copia del str
sarebbe rimasto "vivo" in main()
fino main()
rendimenti.
No, l'esemplare di rinvio è una temporanea std::string
, che sarà distrutta alla fine della dichiarazione in cui è stato creato, vale a dire prima della std::cout << cStr << std::endl;
. Quindi cStr
diventa ciondolato, il dereferimento su di esso porta a UB, tutto è possibile.
È possibile copiare il valore temporaneo restituito su una variabile denominata o associarlo a un riferimento di valore o valore di riferimento di const
(la durata del temporaneo verrà estesa fino a quando il riferimento non si estende). Come ad esempio:
std::string s1 = getString(); // s1 will be copy initialized from the temporary
const char* cStr1 = s1.c_str();
std::cout << cStr1 << std::endl; // safe
const std::string& s2 = getString(); // lifetime of temporary will be extended when bound to a const lvalue-reference
const char* cStr2 = s2.c_str();
std::cout << cStr2 << std::endl; // safe
std::string&& s3 = getString(); // similar with above
const char* cStr3 = s3.c_str();
std::cout << cStr3 << std::endl; // safe
Ecco una spiegazione da 10.4.10 oggetti temporanei [class.temp]] [The.C++ Programming.Language.Special.Edition.]:
A meno legato a un riferimento o utilizzato per inizializzare un oggetto denominato, un oggetto temporaneo viene distrutto alla fine dell'espressione completa in che è stato creato. Un'espressione completa è un'espressione che è non una sottoespressione di qualche altra espressione.
La classe di stringhe standard ha una funzione membro c_str() che restituisce una matrice di caratteri stile C, a terminazione zero (§3.5.1, §20.4.1). Inoltre, l'operatore + è definito per indicare la concatenazione di stringhe. Queste sono strutture molto utili per le stringhe. Tuttavia, in combinazione possono causare problemi oscuri. Per esempio:
void f(string& s1, string& s2, string& s3)
{
const char* cs = (s1 + s2).c_str();
cout << cs ;
if (strlen(cs=(s2+s3).c_str())<8 && cs[0]==´a´) {
// cs used here
}
}
Probabilmente, la tua prima reazione è "ma non farlo", e sono d'accordo. Tuttavia, tale codice viene scritto, quindi vale la pena sapere come è interpretato .
Un oggetto temporaneo di stringa di classe viene creato per contenere s1 + s2. Successivamente, un puntatore a una stringa in stile C viene estratto da quell'oggetto. Quindi - alla fine dell'espressione - l'oggetto temporaneo viene cancellato. Ora, dove è stata allocata la stringa in stile C? Probabilmente come parte dell'oggetto temporaneo che contiene s1 + s2 e che non è garantito che l'archiviazione esista dopo che il temporaneo è stato distrutto. Di conseguenza, cs punti per archiviare deallocated. L'operazione di uscita cout < < cs potrebbe funzionare come previsto, ma che sarebbe pura fortuna. Un compilatore può rilevare e mette in guardia contro molte varianti di questo problema.
Il tuo codice funziona bene per me. –
@PriyanshGoel Il comportamento indefinito è così a volte. –
Non riesco a capire perché il comportamento non è definito. –