2010-07-17 7 views
11

Si es así, ¿por qué? ¿Por qué no usa el constructor de copia del tipo de valor?¿std :: vector usa el operador de asignación de su tipo de valor para push_back elements?

me sale el siguiente error:

/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 

corriendo g ++ main.cpp en el siguiente código:

/* 
* 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 solo para 'ClassWithoutAss'. – GManNickG

+2

¿Por qué trabajas el vec.push_back ... no causará ningún problema, pero parece un poco innecesario ... – Goz

+1

¿Es eso un "asno" como en "burro"? – sbi

Respuesta

13

El estándar de C++ 03 dice copiar elementos deben ser Urbanizable y contra copias asignable para ser utilizado en un contenedor estándar. Entonces una implementación es libre de usar lo que quiera.

En C++ 0x, estos requisitos se ponen por operación. (En general, los elementos deben ser movibles y transferibles).

Para obtener lo que desea, debe usar un puntero inteligente como shared_ptr (de Boost, TR1 o C++ 0x), y completamente deshabilitar la capacidad de copiado:

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))); 

Los punteros se pueden copiar muy bien, y el puntero inteligente garantiza que no tenga fugas. En C++ 0x puede hacer esto mejor con un std::unique_ptr, aprovechando la semántica de movimiento. (Realmente no necesita semántica compartida, pero en C++ 03 es más fácil en su forma actual.)

+0

Te creo, pero ¿puedes explicar por qué los indicadores en lugar de definir mis propias operaciones? Push_backs más rápidos? Entonces, ¿no pierdo el tiempo definiendo operaciones? Tendré que buscar en la semántica de movimiento/compartir. Gracias GMan. Solo tengo estos problemas con tu ayuda. ;) – user383352

+0

@drenami: ¿Qué quieres decir? Usé punteros porque quiere tener su clase en el contenedor, pero no puede hacerlo directamente. Una abstracción arriba es un puntero a su clase, en lugar de la clase misma. (Y los indicadores inteligentes solo para evitar fugas.) – GManNickG

+0

Pero podría si definiera un operador de asignación ¿no? Entonces mi pregunta es pro/contra de los dos diseños, uno sin asignación/usando punteros, una asignación definitoria. Ambas son opciones porque puedo escribir ClassWithAss. – user383352

4

El problema aquí es que los tipos en un contenedor deben ser asignables.

Como no define un operador de asignación para su clase, el compilador generará uno para usted. El operador de asignación predeterminado se verá así:

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

En la mayoría de los casos, esto funcionaría. Pero el miembro mem es un const y por lo tanto no se puede asignar. Por lo tanto, la compilación fallará cuando intente generar el operador de asignación.

+1

Prefiero clases con 'Culo' – Balk

Cuestiones relacionadas