2016-11-15 1 views
0

J'essaye de faire void* pour contenir une valeur (pour éviter l'appel par défaut du constructeur).Comment utiliser void * comme support de variable unique? (Ex. Void * raw = SomeClass())

Je veux: -

  • copie K à void * par exemple K k1; --> void* raw=k1;
  • copier void * à K e.g. void* raw; --> K k2=raw;
  • essayer de ne pas casser destructor et provoque une fuite de mémoire
  • ne pas utiliser l'allocation dynamique (tas, la raison de la performance)

Voici ce que j'ai essayé: -

class K{ 
    public: std::string yes="yes" ; 
}; 

int main() { 
    //objective: k1->raw->k2 , then delete "raw" 
    void* raw[sizeof(K)];  //<--- try to avoid heap allocation 
    K k1; 
    static_cast<K>(raw)=k1;  //<--- compile fail 
    K k2= static_cast<K>(raw); 
    std::cout<<k2.yes;   //test 
    static_cast<K&>(raw)::~K(); //mimic destructor 
    return 0; 
} 

Question: Veuillez fournir un code valide qui démontre une manière correcte de le faire.

J'ai trouvé comment utiliser le placement nouveau (https://stackoverflow.com/a/4756306/3577745), mais pas trouvé comment utiliser void* pour une variable qui n'est pas un tableau.

C++ est nouveau pour moi.

Modifier:
Je suis en train d'écrire une collection très personnalisée (tableau).
Chaque élément est encapsulé dans une structure personnalisée KCap kcap (avec uniquement 1 élément, c'est-à-dire K).
Ainsi, je dois déclarer K k comme champ de l'encapsulateur KCap.
Cependant, je veux éviter le constructeur par défaut de K, donc je pense que void* peut résoudre mon problème.

+1

Cela sent comme si vous aviez un autre problème que vous pensez que ceci résoudra. Alors pourquoi ne pas poser des questions sur * ça * à la place? – StoryTeller

+0

La variable 'raw' est un * tableau * de pointeurs, pas un seul objet non typé. Pour cela, un tableau de 'char' est nécessaire, ainsi que le placement' new'. –

+0

Ce que vous essayez de faire n'a pas de sens. Un 'void *' est utilisé pour contenir un type de pointeur arbitraire, et non un type arbitraire d'un autre objet. – davmac

Répondre

3

Ce que vous essayez de faire n'a pas de sens. Un void * est utilisé pour contenir un type de pointeur arbitraire, et non un type arbitraire d'un autre objet. Si vous souhaitez utiliser le stockage pour un type d'objet arbitraire, utilisez un char[].

D'autres problèmes avec votre code incluent que vous devez assurer l'alignement correct du stockage brut, utilisez reinterpret_cast à une référence plutôt que static_cast à une non-référence, votre syntaxe d'appel de destructeur sur place est erronée, et que vous ne ne construisons pas l'objet K dans le stockage "brut". Voici une version corrigée:

#include <string> 
#include <iostream> 

class K{ 
    public: std::string yes="yes" ; 
}; 

int main() { 
    //objective: k1->raw->k2 , then delete "raw" 
    alignas(alignof(K)) char raw[sizeof(K)];  //<--- try to avoid heap allocation 
    K k1; 
    new (reinterpret_cast<K *>(&raw)) K(k1);  //<--- compile now succeeds :) 
    K k2= reinterpret_cast<K &>(raw); 
    std::cout << k2.yes << std::endl;   //test 
    reinterpret_cast<K&>(raw).K::~K(); // call destructor 
    return 0; 
} 
+0

Vous devriez supprimer le commentaire" compile fail ";-). A moins d'échouer. # –

+0

@davmac Pensez-vous qu'une réponse (similaire à la vôtre) dans une autre question http://stackoverflow.com/a/15343/3577745 souffre du problème d'alignement mentionné? – javaLover

+1

@ javaLover Je pense parce qu'il alloue le stockage 'char' en utilisant' new', c'est ok; c'est-à-dire que 'new' alloue un stockage convenablement aligné pour tout objet. Mais je ne suis pas entièrement sûr, tbh. – davmac