C++: comment faire pour créer un tableau d'objets sur la pile?
Considérer le morceau suivant du code Java.
int N = 10;
Object obj[] = new Object[N];
for (int i = 0; i < N; i++) {
int capacity = 1000 * i;
obj[i] = new ArrayList(capacity);
}
Car en Java, tous les objets en direct sur le Tas, le tableau n'est pas
contenir les objets eux-mêmes, mais les références à des objets. Aussi,
le tableau lui-même est aussi un objet, donc elle vit sur le tas.
Quel est l'équivalent en C++, mais en gardant la matrice et des objets sur
la pile, afin d'éviter autant que possible d'avoir besoin de nouvelles et de les supprimer ?
Edit: changé le code pour utiliser un constructeur personnalisé.
OriginalL'auteur Leonel | 2008-11-26
Vous devez vous connecter pour publier un commentaire.
Pour un tableau de ArrayList d'objets:
Les objets sera initialisé par défaut, ce qui est bien pour les types définis par l'utilisateur, mais peut ne pas être ce que vous voulez pour builtin-types.
Considérer aussi:
Ce initialise les objets en copiant tout ce que vous transmettez en tant que second paramètre. Donc ils sont tous les mêmes, mais pas nécessairement par défaut. Et comme litb le souligne, "10" dans le vecteur peut être remplacé par une autre expression constante, tandis que le "10" dans la déclaration de tableau ne peut pas.
Ce n'est pas réellement mis à l'ArrayList d'objets sur la pile, il met tous les 10 en une seule allocation dans le tas. Donc il peut très rarement des problèmes de rendement, si vous ne pouvez vraiment pas se permettre une allocation unique. Cependant, le std::vector est sur la pile, et il supprime un tas d'objets qu'il utilise lorsqu'il est détruit. Afin de vous assurer que vos ressources sont libérées, le vecteur se comporte "comme si" il était tous sur la pile.
Noter que le mélange d'un conteneur d'Objet, avec une liste de tableaux de valeurs, comme vous le faites dans votre exemple de code Java, est périlleuse en C++. Fondamentalement, vous ne pouvez pas le faire, même si ArrayList s'étend de l'Objet, parce que la matrice contient uniquement le stockage de 10 Objets, et ArrayList requiert probablement plus d'octets pour stocker de l'Objet. Le résultat est que toute ArrayList vous essayez de le copier dans le tableau permettrait d'obtenir des "tranches": seule la première partie de sa représentation, qui est mis dans le tableau.
Si vous voulez un contenant d'un type dire qu'il contient des Objets, mais qui en réalité contient ArrayLists, alors vous avez besoin d'un conteneur de pointeurs. Pour obtenir de bonnes ressources de la manipulation, cela signifie probablement que vous avez besoin d'un conteneur de pointeurs intelligents.
pas de. le vecteur des copies
en effet, ce n'est pas allouer sur la pile, à moins que le vecteur est un autre allocateur.
Oui, c'est pourquoi je vous présente le vecteur comme une alternative à considérer, plutôt que comme une réponse directe à la question. Ce n'est pas un jeu, après tout, il est souvent utile d'offrir des moyens de faire des choses semblables à ce que la question dit, dans l'espoir qu'il réponde aux besoins réels.
OriginalL'auteur Steve Jessop
Simplement déclarer
en C++ crée de 10 par défaut construit des objets de type d'Objet sur la pile.
Si vous souhaitez utiliser un non-constructeur par défaut, qui n'est pas si facile en C++. Il y a peut être un moyen pour la mise en place de la nouvelle, mais je ne pourrais pas vous dire sur le dessus de ma tête.
EDIT: Lien vers d'autres question sur StackOverflow
Comment utiliser le placement de nouvelles pour le tableau est expliqué dans la réponse à la cette question ici sur StackOverflow.
OriginalL'auteur Joris Timmermans
En C++, il n'est pas possible d'avoir un tableau sur la pile avec une taille déterminée au moment de l'exécution. Ici vous utiliser std::vector pour le faire:
Si la taille est connue à la compilation, vous pouvez simplement aller de l'avant avec un simple tableau:
Si vous êtes autorisé à utiliser boost, il est préférable d'utiliser boost::array , car elle fournit des itérateurs comme des conteneurs faire, et vous serez en mesure d'obtenir sa taille à l'aide .size():
ni le "tableau", ni les objets qui sont sur la pile en fait, si vous utilisez la norme de l'allocateur.
En fait, certains compilateurs (notamment g++) prennent en charge la pile de matrices à durée déterminée taille. C'est apparemment un transplanté C99 fonctionnalité appelée Variable de Tableaux de Longueur.
oui, vous avez raison. Que le c99 est pris en charge par gcc. mais le C++ n'en a pas besoin 🙂
OriginalL'auteur Johannes Schaub - litb
Allocation peut être fait de manière "statique" (de la taille connue au moment de la compilation) ou "dynamiquement" (de la taille est déterminée au moment de l'exécution).
Allocation statique est la plaine vieux
À allouer sur la pile, vous avez besoin de la
alloca
fonction d'allocation, qui est essentiellement juste incrémente le pointeur de pile. (ou décrémente... quoi que). La libération se fait automatiquement.De sorte que vous pouvez initialiser un tableau sur la pile comme Nils a montré.
std::vector
peut travail sur la pile si une pile allocateur (la seconde, la lourdeur argument de modèle devector
)Ma conjecture est que Boost fait juste cela.
OriginalL'auteur xtofl
Vous pouvez même attribuer un nombre variable d'objets sur la pile. Vous devez mélange de C et de C++ pour le faire bien.
Code n'est pas testé, mais en principe, il fonctionne de cette manière.
Je dirais qu'il vaut la peine de connaître, pour que les très rares cas où le tas est trop lent et vous savez que la limite supérieure de N et de votre propre pile d'utilisation tels que le tableau sera adaptée. Pas la solution unique, par tout moyen, mais c'est ce qui était demandé...
juste assez 🙂 cependant, il a posé sur un c++ solution. alloca n'est même pas POSIX 🙂
J'ai utilisé le placement de nouvelles une fois dans mes 10 ans en tant que développeur - où il y avait un allouée statiquement tableau que je ne pouvais pas les toucher (ancien de la bibliothèque de code), mais j'ai eu pour obtenir un objet qui n'avait pas de constructeur par défaut. Méchant hack 😉
Je suis d'accord, les gars. Je ne fais jamais de ces hacks dans le code de production.
OriginalL'auteur Nils Pipenbrinck
Si vous arrive d'utiliser Qt, vous pouvez utiliser le QVarLengthArray
Il prend une taille en tant que second paramètre du modèle, et il va allouer de manière statique un tableau de cette taille, et de l'utiliser comme support pour le tableau au lieu de le tas comme un std::vector ou QVector. Si vous ajoutez de plus que le modèle spécifié par la taille, il va utiliser tas de répartition de la place.
Exemple:
Si vous restez en dessous du paramètre de modèle taille, vous allez éviter la dégradation des performances d'une allocation de tas - vous allez effectivement avoir un allouée dynamiquement en fonction de pile de tableau. Le seul inconvénient est qu'il est un gaspillage de mémoire si vous n'utilisez pas exactement autant d'éléments que le modèle de paramètre spécifie: Si vous utilisez trop peu, puis les espaces vides sont gaspillés. si vous utilisez trop, puis l'ensemble de la pile zone allouée est gaspillée.
Parfois performances de trading pour mémoire en vaut la peine, et parfois il ne l'est pas. Je déconseille aveuglément à l'aide de cette classe - utiliser seulement si vous savoir via le profilage que l'allocation de tas de std::vector est l'un de votre programme d'étranglement.
OriginalL'auteur Elliott