2010-07-20 2 views
3

Le sujet le plus proche de ma question est here. Je suis en train de compiler le code suivant avec gcc:Appeler le constructeur de classe à partir d'un nouvel opérateur sur GNU - utiliser la classe invalide

#include <malloc.h> 

class A 
{ 
public: 
    A(){}; 
    ~A(){}; 
};//class A 

int main() 
{ 
    A* obj = (A*) malloc(sizeof(A)); 
    if(obj==0) return 1 ; 
    obj->A::A(); /*error: invalid use of 'class A' */ 
    obj->A::~A(); 
    free(obj); 
    return 0; 
};// 

Depuis la ligne de commande je compilez le code avec:

$ g++ -o main main.cpp 
main.cpp: In function 'int main()': 
main.cpp:22: error: invalid use of 'class A'

Pouvez-vous s'il vous plaît me diriger dans la bonne direction?

+0

duplication possible de [C++, est-il possible d'appeler un constructeur directement, sans nouveau?] (Http://stackoverflow.com/questions/2494471/c-is-it-possible-to-call-a-constructor -directement-sans-nouveau) – kennytm

+3

Pourquoi le faites-vous de cette façon? Essayez-vous d'éviter les exceptions en cas d'échec? Utilisez simplement 'new (nothrow)', puis testez la valeur NULL. –

+0

@Amardeep, un exemple auquel je peux penser est l'implémentation du serveur web-service, où vous ne pouvez pas supprimer des objets tant qu'ils sont sérialisés et quand ils sont sérialisés vous n'avez pas le thread de contrôle, donc vous ne pouvez pas appeler destructor -kit ou framework doit «libérer» cela. la mémoire fournie et gérée pour vous est à travers 'malloc' alors il n'y a pas d'autre moyen que de l'utiliser. * (et s'ils ne fournissent pas l'opérateur 'new' personnalisé, qui fait l'allocation sur leur tas et les supprime aussi.) * –

Répondre

6

Vous ne pouvez pas appeler un constructeur sur un objet; un constructeur ne peut être appelé que dans la création d'un objet donc, par définition, l'objet ne peut pas encore exister.

La manière de procéder est avec l'emplacement new. Vous n'avez pas besoin d'envoyer votre déclaration malloc. Il devrait être void * car il ne retourne pas un pointeur sur un A; seulement un pointeur vers la mémoire brute dans laquelle vous envisagez de construire un A.

E.g.

void* mem = malloc(sizeof(A)); 

A* obj = new (mem) A(); 
obj->~A(); 

free(mem); 
2

Il n'y a pas besoin de malloc entreprise en C++. Il suffit de faire:

A* obj = new A(); 

new alloue la mémoire et appelle le constructeur pour vous.

Et, pour le détruire, faire:

delete a; 

delete appelle la méthode deconstructor et libère la mémoire.

+0

malloc est une affaire sérieuse. –

8

Vous souhaitez un placement-nouveau à la place.

void* ptr = malloc(sizeof(A)); 
A* obj = new(ptr) A; 
+0

Comment l'allocateur fonctionne-t-il dans ce cas, de la même manière que son propre tas? –

+1

@Gollum: Aucune allocation n'est faite si vous utilisez le placement nouveau. Il suffit de mettre 'ptr' comme' this' et appelle le constructeur. – kennytm

+0

@KennyTM, parlait d'allouer un gros buffer et ensuite de faire plusieurs 'placement-new' pour tous les objets que j'ai besoin d'allouer sur ce gros buffer (comme n chaînes). (comment n objets seraient placés, il devrait avoir son propre algorithme pour s'adapter à ces objets - qu'en est-il de 'fragmentation ' –

2

Étant donné que vous utilisez C++, il est inutile de revenir à malloc. Vous pouvez l'écrire en termes d'opérateur new

int main() { 
    if(A* obj = new (std::nothrow) A()) { 
    delete obj; 
    return 0; 
    } 
    return 1; 
} 

La version nothrow de new renvoie un pointeur NULL en cas d'échec l'allocation, au lieu de lancer une exception.