2010-05-25 18 views
5

El siguiente fragmento da la advertencia:Advertencia de "objeto temporal": ¿soy yo o el compilador?

[C++ Warning] foo.cpp(70): W8030 Temporary used for parameter '_Val' in call to 'std::vector<Base *,std::allocator<Base *> >::push_back(Base * const &)' 

.. en la línea indicada.

class Base 
{ 
}; 

class Derived: public Base 
{ 
public: 
Derived() // << warning disappears if constructor is removed! 
{ 
}; 
}; 

std::vector<Base*> list1; 
list1.push_back(new Base); 
list1.push_back(new Derived); // << Warning on this line! 

compilador es Codegear C++ Builder 2007.

Curiosamente, si el constructor para Derivado se elimina, la advertencia desaparece ... ¿Soy yo o el compilador?

EDIT: La única forma que he encontrado para eliminar la advertencia es que algo similar a esto:

Derived * d; 
list1.push_back(d = new Derived); // << No warning now... 
+0

No hay advertencia en este código con gcc. – kriss

+0

Probablemente no sea * todo * el código. Do Base y Derived tienen constructores (generadores no compiladores)? –

+0

@MadKeithV - dar o tomar un #include , que es TODO el código. Empecé con un caso mucho más complejo y lo reduje al mínimo que muestra el problema anterior. – Roddy

Respuesta

2

intento simple:

list1.push_back(new Derived()); 

Me temo que hay algo acerca de POD (con constructores triviales) vs no-POD pasando aquí.

EDITAR:

Dado que el código se compila bien con gcc.3.4.2 (--pedantic) Me gustaría decir que es un capricho compilador. Me estoy inclinando hacia la explicación MarkB, es decir, el compilador crea un temporal aunque no entiendo por qué sería necesario y luego me quejo cuando lo asigno al const& ... pero todavía estoy perplejo.

+0

buen intento, pero no hay diferencia! – Roddy

+0

Es molesto que no tenga el compilador a mano para experimentar con él:/Es realmente extraño que no se genere la misma advertencia para 'Base': ¿o tal vez es porque' Base' no tiene un constructor definido por el usuario? –

+0

Base tenía un constructor definido por el usuario, pero lo recorté, ya que no supuso ninguna diferencia para el problema. es decir, el uso de 'nueva base' nunca dio una advertencia ... – Roddy

1

Desde list1 es un vector de Base*, la función push_back de la lista se va a esperar un parámetro de tipo Base* const&, mientras que su nueva está proporcionando Derived*. Para pasar por referencia (según sea necesario en push_back) el compilador necesita un objeto real del tipo de referencia, en este caso Base*. Hay una conversión implícita disponible de Derived* a Base* que el compilador usa para crear un objeto temporal de tipo Base* para pasar al push_back, y el compilador le advierte que está creando este temporal.

La razón funciona cuando se asigna a una variable es que ya no hay una implícita temporal necesaria es:. Se puede convertir implícitamente la variable llamada a Base* implícita y pasar esa referencia en

Creo que se puede silenciar esta advertencia diciendo push_back para tratar el puntero como un Base*:

list1.push_back(static_cast<Base*>(new Derived));

+0

Hmm. El reparto no cambia las cosas, pero veo lo que estás diciendo. Sin embargo, todavía no estoy seguro de la diferencia entre las dos conversiones implícitas. – Roddy

+0

OK, entonces ¿por qué importa la presencia del constructor Derived() ...? – Roddy

+0

Me preguntaba sobre eso pero no tiene sentido para mí. Si 'Derived *' es implícitamente convertible a 'Base *' (como es el caso) entonces ¿por qué un 'Base *' y un 'Derived *' se tratarían de manera diferente? No veo la necesidad de crear un temporal de 'Derived *' a 'Base * const &' (por cierto, compruebe la posición 'const' en su respuesta), y' const & 'puede vincularse a los temporales de todos modos ... esto es molestándome:/ –

1

En una llamada "el paso por referencia", si el tipo de argumento no coincide con el "parámetro formal", entonces el compilador intentará convertir el argumento a el tipo correcto El argumento se considerará como un 'parámetro de valor' si la conversión es exitosa. El compilador genera la advertencia "Temporal utilizado para ..." en este caso.

+0

funcionó para mí. int utilizado en el parámetro sin signo. –

Cuestiones relacionadas