J'ai une classe qui est décrite de cette façon: Je ne peux pas changer la conception de cette classe. P> Comment puis-je créer une instance de cette classe? Avant d'appeler le constructeur, je dois la faire réserver suffisamment de mémoire pour stocker ses données. Il doit donc être sur le tas, pas sur la pile. Je suppose que je veux quelque chose comme p> mais je ne trouve pas un moyen de le faire fonctionner. P> EDIT: Comme les commentateurs ont remarqué, ceci est Pas une très bonne conception globale (avec des astuces non-normes telles que données [0] code>), il s'agit d'une bibliothèque que je suis obligée d'utiliser ... p> p>
4 Réponses :
Vous pouvez masloc code> la mémoire de l'objet, puis utiliser un
Placement Nouveau code>
pour créer l'objet dans la mémoire précédemment attribuée: void* memory = ::operator new(sizeof(Foo) + sizeof(int) * size);
Foo* foo = new (memory) Foo(size, data);
...
foo->~Foo();
::operator delete(memory); //or ::operator delete(foo);
Serait légèrement plus sûr de faire malloc (tailleof (foo) + ... code> plutôt que
Tailleof (int) code>. Juste au cas où
foo code> obtient un autre membre à l'avenir.
Vous pouvez effectivement éviter MALLOC () et faire VOID * Memory = Nouveau caractère [TIZEOF (FOO) + Taille de (int) * Taille]; Code>
(VOID *) FOO == Memory CODE> est garanti et c'est une bonne chose, sinon vous n'auriez pas suffisamment de mémoire.
@Benvoigt Je n'étais pas sûr de ça.
N'utilisez pas MALLOC code> ou
nouveau caractère [] code> Si vous voulez une mémoire brute, utilisez simplement
:: opérateur nouveau code>. Son seul but dans la vie est d'allouer la mémoire brute.
@Gmannickg C'est vraiment la bonne façon de le faire, mais existe-t-il une différence pratique entre :: opérateur nouveau code> et
malloc code>?
@ZAKINSTER: Vous pouvez remplacer la définition de :: opérateur Nouveau code> avec un gestionnaire de mémoire personnalisé. En utilisant
malloc code>, vous contournez cela.
Après avoir utilisé :: opérateur Nouveau code> et placement
Nouveau code>, ne serait-il pas valide pour simplement
Supprimer FOO; code>?
@ASCHEPLER: Non, vous ne pouvez que Supprimer code> Ce que vous
Nouveau code> 'd. Bien que cela puisse partager le mot lexical "nouveau", ce sont des choses différentes. Pour annuler
:: Opérateur Nouveau code>, vous
:: Opérateur Supprimer code>.
Mais vous avez fait nouveau code> l'objet
foo code> dans l'expression
nouvelle (mémoire) FOO (taille + données) code>. (Bien que ce soit soit
:: supprime foo; code>, pas seulement
Supprimer foo; code>.)
@ASCHEPLER: Ce n'est pas Nouveau code> ing A
foo code>, c'est
nouveau (mémoire) code> ing A
foo code>. :) Il n'y a pas de
Suppr (mémoire) code> dans la langue pour correspondre qui est l'endroit où l'asymétrie frappe (suppression manquante).
N'y a-t-il pas de problèmes d'alignement avec ce genre de choses?
Si vous voulez vraiment être paresseux, utilisez simplement un Vos objets seront mobiles de votre définition. Vous pouvez donc faire ce qui suit en toute sécurité pour éliminer la réaffectation du vecteur lors de ... P> std :: vecteur
auto initialFooValue = Foo(0, 0)
auto fooContainer = std::vector<Foo>(size, initialFooValue);
int i = 0;
for (auto& moveFoo : whereverYouAreFillingFrom)
{
fooContainer[i] = std::move(moveFoo);
++i;
}
C'est une solution que j'ai pensée, mais hélas je suis obligé d'utiliser pour fournir une bibliothèque pour des raisons de performance ...
STD :: Vecteur Code> Le contenu propre est contigu en lui-même, mais il n'est pas contigu avec la structure plus grande.
Vous avez une bibliothèque qui fait cette chose mais ne fournit pas une fonction d'usine? Pour la honte!
Quoi qu'il en soit, tandis que la méthode de Zakinster a raison (j'appellerais directement l'opérateur nouveau au lieu d'un nouveau tableau de caractères, cependant), c'est aussi sujette d'erreur, vous devez donc l'envelopper. P> < Pré> xxx pré>
Oui, il y a un peu de frais généraux ici, mais la plupart de ces choses sont réutilisables. P> P>
Je pense qu'une solution bonne em> C ++ est d'obtenir une mémoire brute avec de nouveau, puis utilisez le placement nouveau pour intégrer votre classe à celle-ci. Obtenir la mémoire brute fonctionne comme ceci: P> xxx pré> construire l'objet dans la mémoire reçue fonctionne comme ceci: p> N'oubliez pas que cela signifie également que vous devez user> manuellement Strong> Nettoyer l'endroit. P> f->~Foo(); // call the destructor
operator delete(f); // free the memory again
Placement
Nouveau code> avec une allocation manuelle pourrait aider.
int Data [0] code> n'est pas valide C ++.
Placement Nouvelle syntaxe:
Nouveau (adresse) Type (Arguments ...); code> où
adresse code> est
vide * code>. Tout ce qui est créé avec placement
nouveau code> doit être détruit avec un appel de destructeur explicite; Je doute d'une manière ou d'une autre que vous voulez faire cela manuellement, vous allez bien écrire un wrapper autour de
FOO code> qui traite d'une allocation / distribution appropriée.
Toute raison pour laquelle vous ne pouvez pas utiliser
std :: vecteur code>?
@Kerreksb: Désolé de Nitpick, mais non, c'est valide C ++; Lorsque la taille est 0, il retournera toujours un pointeur valide, mais la désirficite est indéfinie. Détails: Stackoverflow.com/questions / 1087042 / ...
@ Legends2k: Cela n'a rien à voir avec mon commentaire.
@Philipp, en fait, les méthodes que j'ai cachées font beaucoup de choses utiles, donc je ne peux pas utiliser un
vecteur code> à la place. La bibliothèque je suis censée utiliser fait de nombreuses tours de micro-optimisations, c'est l'un d'entre eux.
Le projet de norme J'ai une section [DCL.Array] où il indique clairement des tableaux "si l'expression constante (5.19) est présente, elle doit être une expression constante intégrale et sa valeur doit être supérieure à zéro."
Ce n'est en effet pas valide C ++, mais il est soutenu par certains compilateurs tels que GCC A >.
Pertinent pour le "est valide?" Discussion: Stackoverflow.com/Questions / 4412749 / ...
@KerReksb: Mon alloc dynamique mal confus. avec stockage automatique :( vient de vérifier la spécification.
Si l'expression constante est présente, elle doit être une expression constante intégrale et sa valeur doit être supérieure à zéro. code> avec
-pedantic Code> g ++ drapeaux
AVERTISSEMENT: ISO C ++ interdit la matrice de taille zéro code>.