Estoy peleando con la siguiente propuesta ahora, y quiero saber argumentos legales y en menor grado morales en su contra o por ello.RVO/NRVO y el constructor público de copia no definida
Lo que teníamos:
#include <vector>
class T;
class C
{
public:
C() { }
~C() { /*something non-trivial: say, calls delete for all elements in v*/ }
// a lot of member functions that modify C
// a lot of member functions that don't modify C
private:
C(C const &);
C& operator=(C const&);
private:
std::vector< T* > v;
};
void init(C& c) { } // cannot be moved inside C
// ...
int main()
{
// bad: two-phase initialization exposed to the clients
C c;
init(c);
// bad: here follows a lot of code that only wants read-only access to c
// but c cannot be declared const
}
Lo que se ha propuesto:
#include <vector>
class T;
class C
{
public:
C() { }
~C() { /*calls delete for all elements in v*/ }
// MADE PUBLIC
C(C const &); // <-- NOT DEFINED
// a lot of member functions that modify C
// a lot of member functions that don't modify C
private:
C& operator=(C const&);
private:
vector< T* > v;
};
C init() // for whatever reason object CANNOT be allocated in free memory
{
C c;
// init c
return c;
}
// ...
int main()
{
C const & c = init();
}
Esto compila y enlaces (y obras) utilizando reciente g ++ (que es el único compilador objetivo) tanto 4.1.2 y 4.4.5 - debido a (N) RVO, nunca se llama al constructor de copias; destructor se llama al final de main() solamente.
Se afirma que la técnica es perfectamente correcta, porque no hay forma de que el constructor de copias pueda ser mal utilizado (si alguna vez se ha generado sería un error del enlazador), y hacerlo público evita que el compilador se queje privado.
Me parece realmente incorrecto usar ese truco, que creo que contradice el espíritu de C++ y se parece más al pirateo, en el mal sentido de la palabra.
Mis sentimientos no son argumentos suficientes, entonces estoy buscando tecnicismos ahora.
Por favor, no publicar los libros de texto C++ cosas aquí:
- Soy consciente de "la regla de tres" y leído a través de 12,8/15 y 12.2 de la Santa estándar; No puedo usar
vector<shared_ptr<T> >
niptr_vector<T>
; - No puedo asignar
C
en la memoria libre y devolverlo deinit
a través deC*
.
Gracias.
Supongo que la construcción de un movimiento no es una posibilidad para usted? –
@Konrad Rudolph: desafortunadamente no (g ++ 4.1.2 es uno de los compiladores que deberíamos soportar, por lo tanto, no hay características 0x). –
"hacerlo público evita que el compilador estúpido se queje de uno privado". - No es un compilador estúpido. El estándar requiere que el constructor de copia sea accesible incluso si se elimina la copia, porque la elisión de copia es opcional. Por lo tanto, si se permite que sea privado, un programa que se base en la elisión para evitar un error no se conformará estrictamente de todos modos, y en este caso el estándar requiere que se lo diagnostique. El compilador te está ayudando a escribir un código portátil, admitiéndolo en contra de tus deseos ;-) –