Lorsque la fonction implique une réallocation, j'ai trouvé que certains compilateurs peuvent enregistrer l'adresse avant l'appel de la fonction. Il entraîne la valeur de retour stockée dans l'adresse non valide.
Il y a un exemple pour expliquer le comportement dans la description ci-dessus.
#include <stdio.h>
#include <vector>
using namespace std;
vector<int> A;
int func() {
A.Push_back(3);
A.Push_back(4);
return 5;
}
int main() {
A.reserve(2);
A.Push_back(0);
A.Push_back(1);
A[1] = func();
printf("%d\n", A[1]);
return 0;
}
Il existe des compilateurs C++ courants et le résultat du test est le suivant.
1
5
5
S'agit-il d'un comportement indéfini?
Le comportement n'est pas défini dans toutes les versions C++ antérieures à C++ 17. La raison simple est que les deux côtés de l'opérateur d'affectation peuvent être évalués dans n'importe quel ordre:
A[1]
Est évalué en premier, vous obtenez un int&
Faisant référence au deuxième élément de A
à ce stade.func()
est évaluée, ce qui peut réallouer le stockage pour le vecteur, laissant au int&
Précédemment récupéré une référence pendante.Uniquement en C++ 17, la règle spéciale 2 pour l'affectation a été faite:
Dans chaque expression d'affectation simple E1 = E2 et dans chaque expression d'affectation composée E1 @ = E2, chaque calcul de valeur et effet secondaire d'E2 est séquencé avant chaque calcul de valeur et effet secondaire d'E1
Avec C++ 17, A[1]
Doit être évalué après l'appel à func()
, qui fournit alors un comportement défini et fiable.