Comment déclarer un tableau d'objets dont la classe n'a pas de constructeur par défaut?
Si une classe n'a qu'un seul constructeur avec un paramètre, comment déclarer un tableau? Je sais que le vecteur est recommandé dans ce cas. Par exemple, si j'ai une classe
class Foo{
public:
Foo(int i) {}
}
Comment déclarer une matrice ou d'un vecteur qui contient 10000 Foo objets?
source d'informationauteur skydoor
Vous devez vous connecter pour publier un commentaire.
Pour un tableau, vous devez fournir un initialiseur pour chaque élément du tableau à l'endroit où vous définissez le tableau.
Pour un vecteur, vous pouvez fournir une instance de copie à chaque membre du vecteur.
par exemple
En fait, vous pouvez le faire aussi longtemps que vous utilisez une liste d'initialisation, comme
cependant, avec 10000 objets ce n'est absolument pas pratique. Je ne suis même pas sûr si vous avez été assez fou pour essayer si le compilateur accepte aussi une liste d'initialisation de cette grande.
sbi a la meilleure réponse pour la plaine de tableaux, mais de ne pas donner un exemple. Alors...
Vous devez utiliser le placement de nouvelles:
Garder à l'esprit que lorsque vous utilisez le placement de nouvelles, vous êtes responsable de l'appel des objets destructeurs -- le compilateur ne pas le faire pour vous:
C'est la seule fois que vous verrez jamais une légitime appel explicite au destructeur.
NOTE: La première version de ce eu un bug subtil lors de la suppression de la "place". Il est important de jeter le "lieu" vers le même type qui a été newed. En d'autres termes,
fooArray
doivent être rejetés surchar *
lors de la suppression. Voir les commentaires ci-dessous pour une explication.Vous auriez besoin de faire un tableau de pointeurs Foo.
Lorsque vous déclarez un objet qui n'a pas de constructeur par défaut, vous devez l'initialiser dans la déclaration.
Il en va de même pour les tableaux de ces types:
Dans votre cas, vous trouverez probablement qu'il est impossible d'initialiser tous les 10 000 éléments comme ça, alors vous pourriez envisager de repenser si la classe ne devriez vraiment pas avoir un constructeur par défaut.
La seule manière de définir un tableau d'une classe sans constructeur par défaut serait d'initialiser tout de suite - pas vraiment une option avec 10000 objets.
Vous pouvez, cependant, d'allouer suffisamment de mémoire brute selon la façon dont vous le souhaitez et de les utiliser de placement
new
pour créer les objets de la mémoire. Mais si vous voulez faire cela, il est préférable d'utiliserstd::vector
qui fait exactement cela:Vous devez utiliser l'agrégation de l'initialiseur, avec 10000 de inidividual initialiseurs entre les
{}
Bien sûr, en précisant 10000 initialiseurs est quelque chose du domaine de l'impossible, mais vous l'avez demandé vous-même. Vous avez voulu déclarer un tableau de 10000 objets avec pas de constructeur par défaut.
Une autre option pourrait être d'utiliser un tableau de
boost::optional<Foo>
:Seul inconvénient est que vous aurez accès à des éléments avec le pointeur de la syntaxe:
Vous devez aussi être prudent de ne pas accéder à un élément non.
Un autre inconvénient est que ce n'est pas une véritable alternative à un tableau de
Foo
car vous ne serez pas en mesure de les transmettre à une fonction qui attend le dernier.Dans droit en C, en utilisant
int foo[10000] = {1};
va initialiser le premier élément de tableau de1
et le reste de la matrice à zéro. Est-ce que C++ pas d'initialisation automatique non spécifié membres du groupe, ou est-ce à besoin d'un constructeur par défaut?Si elle fait sens pour votre classe, vous pouvez fournir une valeur par défaut pour votre paramètre de constructeur:
Vous avez maintenant un constructeur par défaut. (Un "constructeur par défaut" est un constructeur qui peut être appelé sans arguments: FAQ)
Je recommande aussi de faire votre constructeur explicite, comme je l'ai fait ci-dessus. Il va vous empêcher d'obtenir
Foo
s deint
s lorsque vous ne voulez pas en faire la demande.De l'essayer.
La bonne façon est d'utiliser à
std::aligned_storage
. Vous aurez à construire manuellement et de détruire les éléments ainsi que lesreintrepret_cast
lorsque vous souhaitez accéder à un élément. Je vous recommande d'écrire une petite classe wrapper autour destorage_t
pour prendre soin de cela. Quelqu'un a mentionné l'aide deboost::optional
qui utilise un booléen et un storage_t sous le capot. Cette méthode vous permet d'économiser un bool.