Puis-je appeler explicitement le constructeur, sans utiliser new
, si j'ai déjà une mémoire pour l'objet?
class Object1{
char *str;
public:
Object1(char*str1){
str=strdup(str1);
puts("ctor");
puts(str);
}
~Object1(){
puts("dtor");
puts(str);
free(str);
}
};
Object1 ooo[2] = {
Object1("I'm the first object"), Object1("I'm the 2nd")
};
do_smth_useful(ooo);
ooo[0].~Object1(); // call destructor
ooo[0].Object1("I'm the 3rd object in place of first"); // ???? - reuse memory
Sorte de. Vous pouvez utiliser placement new pour exécuter le constructeur en utilisant la mémoire déjà allouée:
#include <new>
Object1 ooo[2] = {Object1("I'm the first object"), Object1("I'm the 2nd")};
do_smth_useful(ooo);
ooo[0].~Object1(); // call destructor
new (&ooo[0]) Object1("I'm the 3rd object in place of first");
Donc, vous utilisez toujours le mot clé new
, mais aucune allocation de mémoire n'a lieu.
Je pense que vous recherchez un placement nouveau. C++ FAQ Lite a un bon résumé de la façon dont vous faites cela. Il y a quelques accrochages importants à partir de cette entrée:
#include <new>
pour utiliser la nouvelle syntaxe de placement.Permettez-moi de vous montrer un code sur la façon dont cela peut être fait, à la fois dans la construction et la destruction
#include <new>
// Let's create some memory where we will construct the object.
MyObject* obj = (MyObject*)malloc(sizeof(MyObject));
// Let's construct the object using the placement new
new(obj) MyObject();
// Let's destruct it now
obj->~MyObject();
// Let's release the memory we used before
free(obj);
obj = 0;
J'espère que le résumé ci-dessus clarifie les choses.
Littéralement, NON, vous ne pouvez pas le faire sans le "nouveau" mot clé. Voir toutes les réponses sur le placement nouveau pour savoir comment utiliser le mot-clé "nouveau" pour appeler le constructeur sans allouer réellement de mémoire.
Oui, lorsque vous avez votre propre tampon alloué, vous utilisez new placement. Brian Bondy a une bonne réponse ici dans une question connexe:
Vous pouvez appeler un destructeur, mais la mémoire ne sera pas récupérée et votre appel sera équivalent à un appel de fonction. Vous devez vous rappeler que sous le destructeur fait 2 choses: détruit l'objet en fonction de vos spécifications et récupère la mémoire. Puisque votre dtor sera de toute façon appelé pour un objet alloué sur la pile, l'appeler deux fois peut entraîner un comportement indéfini.
Oui, en utilisant placement new - comme ci-dessus, mais vous pourriez envisager d'avoir une deuxième classe d'usine pour gérer le stockage, même si cela signifie copier un objet. memcpy () est généralement bon marché pour les petits objets.
Vous pouvez utiliser le modèle suivant
template <typename T, typename... Args>
inline void InitClass(T &t, Args... args)
{
t.~T();
new (&t) T(args...);
}
usage:
struct A
{
A() {}
A(int i) : a(i) {}
int a;
} my_value;
InitClass(my_value);
InitClass(my_value, 5);