L'arithmétique du pointeur sur le stockage alloué est-elle autorisée depuis C ++ 20?


10

Dans la norme C ++ 20, il est dit que les types de tableau sont de type implicite à vie .

Cela signifie-t-il qu'un tableau d'un type de durée de vie non implicite peut être créé implicitement? La création implicite d'un tel tableau ne provoquerait pas la création des éléments du tableau?

Considérez ce cas:

//implicit creation of an array of std::string 
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to object" (which object?)
std::string * sptr = std::launder(static_cast<std::string*>(ptr));
//pointer arithmetic on not created array elements well defined?
new (sptr+1) std::string("second element");

Ce code n'est-il plus UB depuis C ++ 20?


Peut-être que c'est mieux ainsi?

//implicit creation of an array of std::string 
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to the array of 10 std::string" 
std::string (* sptr)[10] = std::launder(static_cast<std::string(*)[10]>(ptr));
//pointer arithmetic on an array is well defined
new (*sptr+1) std::string("second element");

1
Je viens de faire une recherche dans le (brouillon) standard C ++ 20, et je n'ai rien trouvé qui décrit les tableaux comme un "type de vie implicite" (et, oui, j'ai cherché des variantes). Veuillez fournir une description plus détaillée de votre réclamation (par exemple, section et clause dans la norme). Un peu difficile de répondre à votre question sans être en mesure de trouver la source, sans parler de tout contexte pertinent.
Peter

1
@Peter: eel.is/c++draft/basic.types#9 , dernière phrase
geza

Je regardais le PDF open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4849.pdf (apparemment le dernier projet de travail) et il n'a même pas cette phrase. Il semble que vous devrez également trouver la signification de "durée de vie implicite". Je soupçonne que votre lien a peut-être détecté des "modifications en cours" qui n'ont même pas été transformées en versions de travail publiées.
Peter

1
@Peter Les changements sont le résultat de la fusion de P0593 dans la norme de la récente réunion de Prague. Ils n'ont pas encore publié le projet résultant, mais vous pouvez voir le libellé fusionné dans ce commit .
noyer

Réponses:


3

Cela signifie-t-il qu'un tableau d'un type de durée de vie non implicite peut être créé implicitement?

Oui.

La création implicite d'un tel tableau ne provoquerait pas la création des éléments du tableau?

Oui.

C'est ce qui rend std::vectorimplémentable en C ++ ordinaire.


Pourriez-vous également confirmer que std::launder(static_cast<std::string*>(ptr))ne renvoie pas de pointeur sur le premier élément du tableau car il ne fait pas partie de sa durée de vie, mais qu'il std::launder(static_cast<std::string(*)[10]>(ptr))renvoie un pointeur sur le tableau, car le tableau est compris dans sa durée de vie?
Oliv

Cela me semble correct.
TC

@Oliv Et je suppose que le std::laundern'est pas réellement nécessaire, car eel.is/c++draft/intro.object#11 garantit que ptrcela pointera déjà vers le tableau?
noyer

@walnut, ça m'a manqué. Un static_castto std::string (*) [10]devrait donc suffire! tx.
Oliv

@Oliv Mais je suppose que la question devient alors de savoir si votre premier exemple sans le std::laundersera bien défini. Il n'y a aucun std::stringobjet vers ptrlequel pointer, mais pourrait pointer vers le tableau, de sorte que le transtypage statique laissera la valeur inchangée et sptrpointera également vers le tableau. Avec std::launderelle, UB est simplement à cause des std::launderexigences de.
noyer
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.