2010-05-25 74 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