2010-07-17 26 views
11

Si oui, pourquoi? Pourquoi n'utilise-t-il pas le constructeur de copie du type de valeur?Est-ce que std :: vector utilise l'opérateur d'affectation de son type de valeur à des éléments push_back?

je reçois l'erreur suivante:

/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/vector.tcc: In member functio 
n `ClassWithoutAss& ClassWithoutAss::operator=(const ClassWithoutAss&)': 
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/vector.tcc:238: instantiate 
d from `void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterato 
r<typename _Alloc::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = 
ClassWithoutAss, _Alloc = std::allocator<ClassWithoutAss>]' 
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_vector.h:564: instantia 
ted from `void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = Class 
WithoutAss, _Alloc = std::allocator<ClassWithoutAss>]' 
main.cpp:13: instantiated from here 
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/vector.tcc:238: error: non-st 
atic const member `const int ClassWithoutAss::mem', can't use default assignment 
operator 

en cours d'exécution g ++ main.cpp sur le code suivant:

/* 
* ClassWithoutAss.h 
* 
*/ 

#ifndef CLASSWITHOUTASS_H_ 
#define CLASSWITHOUTASS_H_ 

class ClassWithoutAss 
{ 

public: 
    const int mem; 
    ClassWithoutAss(int mem):mem(mem){} 
    ClassWithoutAss(const ClassWithoutAss& tobeCopied):mem(tobeCopied.mem){} 
    ~ClassWithoutAss(){} 

}; 

#endif /* CLASSWITHOUTASS_H_ */ 

/* 
* main.cpp 
* 
*/ 

#include "ClassWithoutAss.h" 
#include <vector> 

int main() 
{ 
    std::vector<ClassWithoutAss> vec; 
    ClassWithoutAss classWithoutAss(1); 
    (vec.push_back)(classWithoutAss); 

    return 0; 
} 
+13

+1 si seulement pour 'ClassWithoutAss'. – GManNickG

+2

Pourquoi est-ce que vous mettez entre parenthèses le vec.push_back ... cela ne causera pas de problèmes mais semble un peu inutile ... – Goz

+1

Est-ce un "cul" comme dans "âne"? – sbi

Répondre

13

La norme C++ 03 indique les éléments doivent être copier-et contre la copie constructible assignable pour être utilisé dans un conteneur standard. Ainsi, une implémentation est libre d'utiliser ce qu'elle veut.

En C++ 0x, ces besoins sont définis par opération. (En général, les éléments doivent être déplacer-et move-constructible cessible.)

obtenir ce que vous voulez, vous devez utiliser un pointeur intelligent comme shared_ptr (soit de Boost, TR1, ou C++ 0x), et complètement désactiver la capacité de copie:

class ClassWithoutAss 
{ 
public: 
    const int mem; 

    ClassWithoutAss(int mem):mem(mem){} 
    // don't explicitly declare empty destructors 

private: 
    ClassWithoutAss(const ClassWithoutAss&); // not defined 
    ClassWithoutAss& operator=(const ClassWithoutAss&); // not defined 
}; 

typedef shared_ptr<ClassWithoutAss> ptr_type; 

std::vector<ptr_type> vec; 
vec.push_back(ptr_type(new ClassWithoutAss(1))); 

Les pointeurs peuvent être copiés très bien, et le pointeur intelligent garantit que vous ne fuyez pas. En C++ 0x vous pouvez le faire mieux avec un std::unique_ptr, en profitant de la sémantique de mouvement. (Vous n'avez pas réellement besoin d'une sémantique partagée, mais en C++ 03, c'est plus simple en l'état.)

+0

Je vous crois, mais pouvez-vous expliquer pourquoi les pointeurs plutôt que de définir mes propres opérations? Push_backs plus rapides? Donc je ne perds pas mon temps à définir des opérations? Je vais devoir regarder dans la sémantique de mouvement/partage. Merci GMan. J'ai seulement ces problèmes avec votre aide. ;) – user383352

+0

@drenami: Que voulez-vous dire? J'ai utilisé des pointeurs parce que vous voulez avoir votre classe dans le conteneur, mais vous ne pouvez pas le faire directement. Une abstraction ci-dessus est un pointeur vers votre classe, plutôt que vers la classe elle-même. (Et les pointeurs intelligents juste pour éviter les fuites.) – GManNickG

+0

Mais je pourrais si j'ai défini un opérateur d'affectation droite? Donc ma question est pro/contre des deux conceptions - une sans affectation/en utilisant des pointeurs, une affectation de définition. Les deux sont des options parce que je peux écrire ClassWithAss. – user383352

4

Le problème ici est que les types dans un conteneur doivent être assignables. Comme vous ne définissez pas d'opérateur d'affectation pour votre classe, le compilateur en générera un pour vous. L'opérateur d'affectation par défaut ressemblera à ceci:

ClassWithoutAss& operator=(ClassWithoutAss const& rhs) 
{ 
    mem = copy.mem; 
    return *this; 
} 
// The compiler generated assignemtn operator will copy all members 
// using that members assignment operator. 

Dans la plupart des cas, cela fonctionnerait. Mais le membre mem est un const et donc inassignable. Par conséquent, la compilation échouera lorsqu'elle tentera de générer l'opérateur d'affectation.

+1

Je préfère les cours avec 'Ass' – Balk