Я получил этот класс:
class myClass
{
private:
struct tm minDate, maxDate;
public:
myClass();
struct tm GetMinDate() {return minDate;};
struct tm GetMaxDate() {return maxDate;};
};
и этот вызов функции
SetMinMaxDate(struct tm *MinDate, struct tm *MaxDate);
следующий код
myClass myInstance;
SetMinMaxDate(&myInstance.GetMinDate(), &myInstance.GetMaxDate());
Работает хорошо и с MSVC 2010 и 2005 предупреждений не генерируется. Но если я скомпилирую его с Intel C ++, я получу предупреждение
warning #1563: taking the address of a temporary
В соответствии с эта связанная тема
Время жизни временного объекта (также известного как rvalue) связано
в выражение и деструктор для временного объекта
вызывается в конце полного выражения
SetMinMaxDate копирует содержимое, переданное с указателями. Сам указатель не сохраняется.
Таким образом, 2 временных элемента tm должны быть действительными до тех пор, пока SetMinMaxDate не вернется.
Есть ли проблема в этом коде или это ложный позитив для Intel C ++?
РЕДАКТИРОВАТЬ:
Я нашел еще один очень интересный пост, который дает причину такого поведения:
Почему незаконно принимать адрес временного значения?
Это действительное предупреждение, потому что SetMinMaxDate()
не дает никаких гарантий, что он не будет хранить этот указатель для последующего использования. И так как вы передаете указатель на временный, если SetMinMaxDate
сохранить его для дальнейшего использования, это будет проблемой.
Еще одна причина предупреждения заключается в том, что с декларацией SetMinMaxDate
является модифицирующий структуры tm передаются через указатель, и такие модификации будут потеряны, так как это указатель на временный объект.
SetMinMaxDate
было бы лучше объявить как:
SetMinMaxDate(const struct tm & MinDate, const struct tm & MaxDate);
не было бы никакого предупреждения в этом случае. const
позволяет компилятору знать, что он не будет изменять объект и &
указывает на то, что вряд ли будет пытаться сохранить адрес на потом.
В соответствии с пунктом 5.3.1 / 3 стандарта C ++ 11:
Результат одинарный
&
Оператор является указателем на свой операнд. Операнд должен быть lvalue или квалифицированным идентификатором. […]
Не только предупреждение является уместным, я скорее задаюсь вопросом, почему это не ошибка. Ваша программа плохо сформирована, так как временные значения не являются lvalues. Вероятно, MSVC поддерживает это как расширение компилятора, но ценность этого расширения довольно спорная.
myClass myInstance;
{
struct tm a,b;
a = myInstance.GetMinDate();
b = myInstance.GetMaxDate();
SetMinMaxDate(&a, &b);
}
Как ты должен реализовать это.
Согласно моим серым воспоминаниям, вы не можете получить адрес rvalue
— это то, что вы делаете.
Так коротко: Intel C прав
В: Есть ли проблема в этом коде или это ложный позитив для Intel C ++?
A: Я вижу эту проблему в этом коде.
Функция GetMinDate () возвращает значение, которое теоретически может быть сохранено в регистре (ах) процессора. Таким образом, он не имеет адреса. Большинство компиляторов будут хранить возвращаемое значение во временном файле, время жизни которого мимолетно. Пока проблем нет.
struct tm GetMinDate() {return minDate;};
Позже вы ссылаетесь на «адрес» этого результата в
... &myInstance.GetMinDate() ...
Теперь у вас есть проблема. Адрес временного объекта может быть быстро использован другой операцией, например, результатом myInstance.Get *Максимум*Дата().
Рекомендуемая реализация @drahnr — хорошее решение.
Другой, но плохой подход, так как структура tm велика, состоит в передаче параметров в SetMinMaxDate () в качестве значений.
SetMinMaxDate(struct tm MinDate, struct tm MaxDate);