Question

J'ai une classe légère qui contient templated deux objets membres qui sont très rarement utilisés, et donc je voudrais éviter d'appeler leurs constructeurs et destructeurs, sauf dans les rares cas où je les utilise en fait.

Pour ce faire, je « déclare » eux dans ma classe comme ceci:

template <class K, class V> class MyClass
{
public:
   MyClass() : wereConstructorsCalled(false) {/* empty */}
   ~MyClass() {if (wereConstructorsCalled) MyCallPlacementDestructorsFunc();}

   [...]

private:
   bool wereConstructorsCalled;
   mutable char keyBuf[sizeof(K)];
   mutable char valBuf[sizeof(V)];
};

... puis-je utiliser le placement et le placement nouveau supprimer pour mettre en place et abattre les objets que lorsque j'ai réellement besoin de le faire.

La lecture du C ++ FAQ dire que lors de l'utilisation de placement nouveau, je dois veiller à ce que le placement est correctement aligné, ou je courrais des ennuis.

Ma question est, les tableaux seront keyBuf et valBuf être correctement alignées dans tous les cas, ou est-il une étape supplémentaire que je dois prendre pour vous assurer qu'ils seront alignés correctement? (Le cas échéant, une étape non dépendant de la plate-forme serait préférable)

Était-ce utile?

La solution

Il n'y a aucune garantie que vous obtiendrez l'alignement approprié. Les tableaux ne sont en général garantis être aligné pour le type de membre. Un réseau de char est alignée pour le stockage de char.

La seule exception est que les tableaux de char et unsigned char attribués à new sont donnés alignement maximum, de sorte que vous pouvez stocker les types arbitraires en eux. Mais cette garantie ne s'applique pas dans votre cas que vous évitez l'allocation de tas.

TR1 et C ++ 0x ajouter quelques types très utiles si:

std::alignment_of et std::aligned_storage ensemble vous donner une réponse portable (et fonctionnement).

std::alignment_of<T>::value vous donne l'alignement requis pour un T de type. std::aligned_storage<A, S>::type vous donne un type POD avec un alignement A et la taille S. Cela signifie que vous pouvez en toute sécurité écrire votre objet dans une variable de type std::aligned_storage<A, S>::type.

(Dans TR1, l'espace de noms est std::tr1, plutôt que std)

Autres conseils

Puis-je vous demander pourquoi vous voulez les placer dans un tampon char? Pourquoi ne pas simplement créer des objets pointeur de K et V instancier alors quand vous en avez besoin.

Peut-être que je ne comprends pas votre question, mais pouvez-vous faire juste char *keyBuf[..size..];, initialement à définir NULL (non attribué) et la renvoyer la première fois que vous avez besoin?

Qu'est-ce que vous essayez de faire avec le placement nouveau semble risqué et le mauvais style de codage.

En tout cas, l'alignement du code dépend de l'implémentation.

Si vous voulez changer l'utilisation d'alignement Code pack pragma

#pragma pack(push,x)

// class code here

#pragma pack(pop) // to restore original pack value

si x est 1, il n'y aura pas de remplissage entre vos éléments.

Heres un lien pour lire

http://www.cplusplus.com/forum/general/14659/

J'ai trouvé cette réponse publié par SiCrane http: // www .gamedev.net / communauté / forums / topic.asp topic_id = 455233 :

  

Cependant, pour les allocations statiques, il est moins inutile de déclarer le bloc de mémoire dans une union avec d'autres types. Ensuite, le bloc de mémoire sera garanti pour être aligné à l'alignement du type le plus restrictif dans l'Union. Il est encore assez laid de toute façon.

On dirait une union pourrait faire l'affaire!

Je recommande que vous regardez le modèle de boost::optional. Il fait ce que vous avez besoin, même si vous ne pouvez pas l'utiliser, vous devriez probablement à sa mise en œuvre.

Il utilise alignment_of et type_with_alignment pour ses calculs d'alignement et garanties.

Pour faire une très très longue histoire très très court cela ne va pas aider votre performance tout et causer beaucoup de maux de tête et il ne sera pas long avant de vous happer par écrit votre propre managemer mémoire.

Placement nouveau est très bien pour un POD (mais ne vous sauvera pas quoi que ce soit), mais si vous avez un constructeur du tout, alors il ne va pas travailler du tout.

Vous pouvez aussi ne pas dépendre de la valeur de votre variable booléenne si vous utilisez le placement nouveau.

Placement nouveau a des utilisations, mais pas vraiment pour cela.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top