2010-05-25 45 views
5

下面的代碼片段給出了警告:「臨時對象」警告 - 是我還是編譯器?

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

..在指定的行。

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! 

編譯器是CodeGear的C++ Builder的2007年

奇怪的是,如果Derived被刪除的構造,警告消失...... 是我還是編譯器?

編輯:我發現刪除警告的唯一方法就是類似於這樣:

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

此代碼沒有警告與gcc。 – kriss 2010-05-25 14:20:15

+0

這可能不是所有代碼。 Base和Derived是否有構造函數(非編譯器生成的)? – 2010-05-25 14:22:37

+0

@MadKeithV - 給予或採取#include ,這是所有的代碼。我從一個更復雜的案例開始,將其切割成顯示上述問題的裸露骨骼。 – Roddy 2010-05-25 14:31:10

回答

2

簡單的嘗試:

list1.push_back(new Derived()); 

恐怕還有一些是關於POD(與微不足道的構造函數)vs非POD在這裏進行。

編輯

鑑於代碼編譯罰款與gcc.3.4.2(--pedantic)我會說這是一個編譯器的怪癖。我傾向於MarkB解釋,即編譯器創建一個臨時的,即使我不明白爲什麼它會被要求,然後抱怨,當它分配給const& ...但我仍然困惑。

+0

不錯的嘗試,但沒有區別! – Roddy 2010-05-25 14:11:37

+0

令人討厭的是,我沒有編譯器方便地試驗它:/真的很奇怪,同樣的警告不是爲'Base'生成的:或者是因爲'Base'沒有用戶定義的構造函數? – 2010-05-25 14:22:22

+0

Base確實有一個用戶定義的構造函數,但我將其修剪掉,因爲它對問題沒有影響。即使用'新的基地'從來沒有發出警告...... – Roddy 2010-05-25 14:32:37

1

由於list1Base*載體,在列表中push_back功能將會期待Base* const&類型的參數,而你的新的提供Derived*。爲了通過引用傳遞(根據push_back的需要)編譯器需要一個實際的引用類型對象,在這種情況下爲Base*。編譯器使用Derived*Base*之間的隱式轉換來創建類型爲Base*的臨時對象,以便傳入push_back,並且編譯器會警告您正在創建此臨時對象。

,當你把它分配給一個變量,它的工作原理的原因是,不再有一個隱含的臨時需要的:它可以在指定的變量隱式轉換爲Base*隱式並傳入參考

我想你可以沉默這個警告,告訴的push_back治療指針作爲Base*

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

+0

嗯。演員不改變事情,但我明白你在說什麼。不過,我仍然不確定這兩個隱式轉換之間的區別。 – Roddy 2010-05-25 14:42:12

+0

好的,爲什麼Derived()構造函數的存在性很重要......? – Roddy 2010-05-25 14:42:58

+0

我在想這件事,但這對我沒有意義。如果'Derived *'可以隱式轉換爲'Base *'(就像這樣),那麼爲什麼'Base *'和'Derived *'會被區別對待呢?我沒有看到需要從'Derived *'創建一個臨時的''Base * const&'(btw檢查你的答案中的const位置),並且'const&'可以被綁定到臨時對象......無論如何竊聽我:/ – 2010-05-25 14:45:25

1

在「通過引用傳遞」調用,如果參數類型不,「正式的參數」匹配,那麼編譯器將嘗試將參數轉換爲正確的類型。如果轉換成功,該參數將被視爲「值參數」。在這種情況下,編譯器會生成警告「臨時用於......」。

+0

爲我工作。 int在無符號參數中使用。 – 2017-05-05 08:41:46