Pourquoi le non-placement new
expression et delete
expression ont-ils été implémentés en tant que langage intégré au lieu de fonctions régulières?
Si nous avons...
un moyen de demander/restituer de la mémoire à l'OS
un moyen d'invoquer explicitement un constructeur (placement new
)
un moyen d'invoquer explicitement un destructeur (~T()
)
... pourquoi le non-placement new
et delete
ne pourrait-il pas être simplement des fonctions régulières dans la bibliothèque standard? Exemple:
template <typename T, typename... Ts>
T* library_new(Ts&&... xs)
{
auto* ptr = /* request enough memory for `T` from OS */;
new (ptr) T(std::forward<Ts>(xs)...);
return ptr;
}
template <typename T>
void library_delete(T* ptr)
{
ptr->~T();
/* reclaim memory for `T` from OS */
}
Si le but de l'utilisateur était de créer un objet dans un emplacement mémoire, alors new
semblait être une approche naturelle puisque transmettait les références , les modèles variadiques et le placement nouveau n'étaient pas une chose à l'époque. Comme correctement souligné par @ T.C. les modèles ont été publiés en 1990 et le placement nouveau en 1989. Les modèles Variadic, d'autre part, ne sont devenus une partie de C++ qu'en C++ 11.
tl; dr Il n'y avait aucun moyen de transmettre un tas d'arguments à un constructeur de type arbitraire (comme vous pouvez le faire de nos jours avec les fonctions make
).
Ce n'est peut-être pas la meilleure référence, mais c'est ce que Wikipedia dit à propos de placement new
en C++:
Dans les versions antérieures de C++, il n'y avait rien de tel que placement new ; à la place, les développeurs ont utilisé une affectation explicite à
this
dans les constructeurs pour obtenir un effet similaire. Cette pratique a été déconseillée et abolie plus tard, et la troisième édition de The "C++ Programming Language" ne mentionne pas cette technique. La prise en charge du placement du nouvel opérateur a été ajoutée aux compilateurs vers 1995.
Peut-être qu'en 2017, il est possible d'implémenter new
en tant que fonction de bibliothèque standard. Votre implémentation suggérée utilise des fonctionnalités de langage qui ont été ajoutées récemment (bon nombre d'entre elles après 2010).
Le langage C++, cependant, est beaucoup plus ancien (depuis 1983) et au début il n'y avait pas de modèles variadic, pas de typename
, pas de placement new
, pas de références de transfert.
Au début, il n'y avait que le new
normal et ce devait être une fonction de langage à ce moment-là car il n'y avait aucun moyen de l'implémenter comme une fonction de bibliothèque.
S'ils étaient déjà fournis en tant que fonctions autonomes, il serait impossible de leur fournir un remplacement défini par l'utilisateur.
par exemple. en ce moment, selon la norme, il est facile d'écrire mes propres globl new
et delete
ils seront utilisés tout au long du programme.
18.6.2 Allocation et désallocation de stockage [new.delete]
2 Remplaçable: un programme C++ peut définir des fonctions avec l'une ou l'autre de ces signatures de fonction, et ainsi déplacer les versions par défaut définies par la bibliothèque standard C++.
Si ceux-ci étaient fournis comme le reste des fonctions de bibliothèque, alors chaque appel normal à new
ou delete
entraînerait "plus d'une instance de la fonction surchargée correspond aux arguments".