Предупреждение «Временный объект» - это я или компилятор? - PullRequest
5 голосов
/ 25 мая 2010

Следующий фрагмент выдает предупреждение:

[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...

Ответы [ 3 ]

2 голосов
/ 25 мая 2010

Простая попытка:

list1.push_back(new Derived());

Боюсь, что-то здесь происходит с POD (с простейшими конструкторами), а не с POD.

EDIT

Учитывая, что код хорошо компилируется с помощью gcc.3.4.2 (--pedantic), я бы сказал, что это особенность компилятора. Я склоняюсь к объяснению MarkB, то есть компилятору, создающему временный файл, хотя я не понимаю, зачем это нужно, а затем жалуюсь при назначении его на const& ... но я все еще растерялся. *

1 голос
/ 18 июля 2016

В вызове «передача по ссылке», если тип аргумента не соответствует «формальному параметру», компилятор попытается преобразовать аргумент в правильный тип. Аргумент будет считаться «параметром значения», если преобразование выполнено успешно. В этом случае компилятор генерирует предупреждение «Временно используется для ...».

1 голос
/ 25 мая 2010

Поскольку list1 является вектором Base*, функция 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));

...