2010-05-25 11 views
5

Il seguente frammento dà l'avvertimento:Avviso "Oggetto temporaneo": si tratta di me o del compilatore?

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

.. sulla linea indicata.

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! 

compilatore è CodeGear C++ Builder 2007.

Stranamente, se il costruttore per il derivato è cancellato, l'avvertimento va via ... Sono io o il compilatore?

EDIT: L'unico modo che ho trovato per rimuovere l'avviso è quello di qualcosa di simile a questo:

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

Nessun avviso su questo codice con gcc. – kriss

+0

Probabilmente non è * tutto * il codice. Base e Derivati ​​hanno costruttori (quelli non generati dal compilatore)? –

+0

@MadKeithV - aggiungi o prendi #include , ovvero TUTTO il codice. Ho iniziato con un caso molto più complesso e l'ho ridotto alle ossa nude che mostra il problema sopra. – Roddy

risposta

2

prova semplice:

list1.push_back(new Derived()); 

ho paura c'è qualcosa di POD (con costruttori banali) vs non-POD in corso qui.

EDIT:

Dato che il codice viene compilato bene con gcc.3.4.2 (--pedantic) direi che è un capriccio del compilatore. Mi sto appoggiando alla spiegazione MarkB, cioè al compilatore che crea un temporaneo anche se non capisco perché sarebbe richiesto e poi mi lamento quando lo assegno allo const& ... ma sono ancora perplesso.

+0

bel tentativo, ma nessuna differenza! – Roddy

+0

È fastidioso non avere il compilatore a portata di mano per sperimentarlo:/È davvero bizzarro che lo stesso avvertimento non venga generato per 'Base': o forse perché' Base' non ha un costruttore definito dall'utente? –

+0

Base ha un costruttore definito dall'utente, ma l'ho ritagliato perché non ha fatto alcuna differenza rispetto al problema. cioè, l'uso di 'nuova base' non ha mai dato un avvertimento ... – Roddy

1

Dal list1 è un vettore di Base*, la funzione push_back nella lista sta per aspettarsi un parametro di tipo Base* const&, mentre il nuovo sta fornendo Derived*. Per passare per riferimento (come necessario in push_back) il compilatore richiede un oggetto reale del tipo di riferimento, in questo caso Base*. Esiste una conversione implicita disponibile da Derived* a Base* che il compilatore utilizza per creare un oggetto temporaneo di tipo Base* da passare a push_back e il compilatore ti avverte che sta creando questo temporaneo.

Il motivo per cui funziona quando si assegna a una variabile è che non è più un implicito temporaneo bisogno c'è:. Può convertire implicitamente la variabile denominata per Base* implicitamente e passare tale riferimento nella

penso che si può tacere questo avvertimento dicendo push_back trattare il puntatore come un Base*:

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

+0

Hmm. Il cast non cambia le cose, ma vedo quello che stai dicendo. Non sono ancora sicuro della differenza tra le due conversioni implicite. – Roddy

+0

OK, quindi perché la presenza del costruttore di Derived() è importante ...? – Roddy

+0

Mi stavo chiedendo ma non ha senso per me. Se 'Derived *' è implicitamente convertibile in 'Base *' (come è il caso), allora perché un 'Base * 'e un' Derived *' dovrebbero essere trattati in modo diverso? Non vedo la necessità di creare un temporaneo da 'Derived *' a 'Base * const &' (btw controlla la posizione' const' nella tua risposta), e 'const &' può essere limitato ai temporaries comunque ... questo è mi infastidisce:/ –

1

In una chiamata "pass per riferimento", se il tipo di argomento non corrisponde al "parametro formale", quindi il compilatore cercherà di convertire l'argomento in il tipo corretto L'argomento verrà considerato come un "parametro valore" se la conversione ha esito positivo. Il compilatore genera l'avviso "Temporary used for ..." in questo caso.

+0

ha funzionato per me. int usato nel parametro unsigned. –

Problemi correlati