2010-01-20 5 views
6

S'il vous plaît considérer les éléments suivants en place:C++ conteneur STL et la construction

class CMyClass 
{ 
public: 
    CMyClass() 
    { 
    printf("Constructor\n"); 
    } 
    CMyClass(const CMyClass&) 
    { 
    printf("Copy constructor\n"); 
    } 
}; 

int main() 
{ 
    std::list<CMyClass> listMyClass; 

    listMyClass.resize(1); 

    return 0; 
} 

Il produit la sortie suivante:

Constructor

Copie constructeur

Maintenant, mon question est: Comment puis-je éviter le constructeur de copie? Ou pour le dire d'une autre manière: Comment puis-je créer des objets dans un conteneur STL sans l'opération de copie inutile. Existe-t-il un moyen de réaliser une construction "sur place" en utilisant le constructeur par défaut?


Mise à jour - réponses à ce jour:

  1. Il ne peut pas être fait
  2. Utilisez des pointeurs ou des pointeurs intelligents au lieu.

Les pointeurs intelligents sont excessifs pour mon application. Mais je me demande vraiment pourquoi cela ne peut pas être fait. Cela semble être une chose si évidente à vouloir faire. D'autres idées? Je vais même accepter un hack méchant si ça marche ...


Solution

Je pense que je viens de trouver une solution pour mon problème de tous les commentaires et les réponses posées ici. La solution est de construire un objet vide et de le garder dans le seul but de l'utiliser plus tard pour faire des copies propres de. Ensuite, vous pouvez utiliser l'une des méthodes qui prennent une référence (comme push_back ou insert). Cela appelle encore le constructeur de copie pour chaque nouvel objet inséré, mais au moins il est à la fois le constructeur par défaut et constructeur de copie:

int main() 
{ 
    CMyClass Empty; 

    std::list<CMyClass> listMyClass; 

    for (int c=0; c<10; ++c) 
    { 
    listMyClass.push_back(Empty); 
    } 

    return 0; 
} 
+0

Il peut sembler un chose évidente, mais d'un point de vue fonctionnel, peu importe et plusieurs algorithmes (trier, supprimer, ...) utilisent aussi la copie, alors préparez-vous à être copié;) (Voir aussi http: //www.devx .com/tips/Tip/13606) – stefaanv

+0

Une chose évidente à faire? Pourquoi donc? Pourquoi est-ce que copier un problème? – jalf

+0

Évident? Si vous appeliez 'mylist.resize (10)', comment vous attendriez-vous à finir avec dix objets distincts s'ils ne sont pas des copies? – visitor

Répondre

8

De par leur conception, tous les conteneurs C++ Standard Library stockent des copies. Par conséquent, l'appel au constructeur de copie ne peut pas être évité si vous souhaitez stocker des valeurs dans le conteneur - la seule solution consiste à stocker des pointeurs à la place. Si vous souhaitez réduire les frais généraux de copie, examinez l'utilisation du comptage des références.

1

utiliser des pointeurs

std::list<CMyClass*> listMyClass; 
+2

encore mieux: utilisez un pointeur intelligent, créant/détruisant automatiquement l'objet en question – user231967

+2

Juste pas un auto_ptr. Cela va provoquer de mauvaises choses à se produire. –

1

Désolé, pas avec std :: liste et récipients similaires. (Mais vous pouvez écrire votre propre conteneur légèrement différent si vous avez vraiment besoin de cela, et toujours suivre le reste de l'interface STL.)

Vous ne devez pas utiliser le cteur par défaut cependant:

std::list<CMyClass> listMyClass; 
listMyClass.resize(1, obj_to_copy_from); 

Tels que:

std::list<CMyClass> listMyClass; 
listMyClass.resize(1, CMyClass(use, specific, ctor)); 

Redimensionner ressemble:

void list<T>::resize(size_type new_size, T copy_from = T()); 

Ce qui crée un nouvel objet (u chantez le ctor par défaut) par défaut.

0

utiliser un pointeur ou pointeur intelligent (boost :: shared_ptr et non auto_ptr)

1

Il serait utile que vecteur a permis l'initialisation de nouveaux éléments avec le constructeur par défaut sur Redimensionner en raison de la performance, mais cela est pas pris en charge. Si vous en avez vraiment besoin, implémentez un conteneur personnalisé - il n'y a pas d'autre moyen.

0

vous pouvez le faire en C11, pour les versions antérieures, vesry simples peuvent améliorer

vecteur

myclas: public vector<A> 
{ 
    push_back(Aconstructor_parameters) 
    { 
     new(_Mylast++) A(Aconstructor_parameters); 
    } 
}; 

lorsque vous utilisez vous assurer que vous avez utilisé reserve() d'allouer la mémoire

Questions connexes