Почему компилятор не выдает предупреждение, когда объект std::vector объявлен, но никогда не используется?
#include <vector>
class Object
{
};
int main()
{
Object myObject;
std::vector<int> myVector;
}
Компилятор испускает:
warning: unused variable 'myObject' [-Wunused-variable]
Нет предупреждения для myVector
. Зачем? Есть ли способ включить это?
Ответы
Ответ 1
Если объявление (и, таким образом, инициализация и в какой-то момент destructung) произвольный объект имеет видимые побочные эффекты, в общем случае нельзя определить. Конструктор может вызывать функции, определение которых неизвестно компилятору или может зависеть от внешнего состояния или любого другого аспекта, который делает проблему неразрешимой.
В вашем первом случае конструктор тривиален (даже не объявлен), тот же для деструктора. Поскольку Object
не имеет членов, ясно и легко обнаружить, что Object foo
на самом деле ничего.
std::vector
имеет нетривиальный конструктор, который может выделять память (внешнее состояние + функция, определение которой не может быть известно (new ...
)) вместе с нетривиальным деструктором (также внешнее состояние + функция, определение которой может не известно (delete ...
)). Рассуждение о том, безопасно ли удалить декларацию (таким образом, вы можете дать предупреждение, что вы, возможно, должны), невозможно в этом случае, поэтому компилятор должен оставить декларацию в коде (и должен предположить, что объявление существует для причина).
Ярким примером является std::lock_guard
, который используется для блокировки мьютекса при его создании и разблокировки автоматически при его разрушении. Таким образом, мьютекс сохраняется до тех пор, пока объект находится в области видимости; обычно вы вообще не будете обращаться к объекту std::lock_guard
, хотя, тем не менее, полезно объявить его. Это принцип RAII на работе.
Испускать предупреждение в таких случаях было бы неприятностью, что привело бы к тому, что люди отключили предупреждение, что, в свою очередь, сделало бы предупреждение бесполезным. (Компилятор может даже быть сконструирован таким образом, чтобы он выдавал предупреждение только в том случае, если он удалил объявление во время оптимизации, что также является причиной того, что некоторые предупреждения отображаются только в том случае, если определенные оптимизации включены.)
Ответ 2
Это предупреждение генерируется только для тривиальных типов. Компилятор не может найти, будет ли конструкцией вызывать любую внешнюю функцию. Если вы добавите конструктор в класс Object
, тогда компилятор также выдает предупреждение. Gcc позволяет тегировать типы, которые должны генерировать это предупреждение, вы можете сделать это с помощью __attribute__((warn_unused))
:
http://coliru.stacked-crooked.com/a/0130c8ef29c121a1
Пример:
class __attribute__((warn_unused)) Object
{
public:
Object(){}
void use() {}
};
int main()
{
Object myObject; // will give : warning: unused variable 'myObject' [-Wunused-variable]
//myObject.use(); // uncomment to hide this warning
}
[править]
из страницы атрибутов gcc: https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html:
warn_unused Для типов С++ с нетривиальными конструкторами и/или деструкторам невозможно, чтобы компилятор переменная этого типа действительно не используется, если на нее не ссылаются. Эта type сообщает об этом компилятору, что переменные этого типа должны быть предупреждены о том, если они кажутся неиспользуемыми, как и переменные фундаментальные типы. Этот атрибут подходит для типов, которые просто представляют значение, например std::string; это не подходит для типы, которые управляют ресурсом, например std:: lock_guard.
Этот атрибут также принимается в C, но он не нужен, потому что C не имеет конструкторов или деструкторов.
Ответ 3
Как и ответы выше, проверьте также свою документацию компилятора. Некоторые компиляторы могут быть установлены так, чтобы они не отображали одно и то же предупреждение несколько раз. Если вы закомментируете объявление "myObject", вы можете получить такое же предупреждение для "myVector". Когда "mObject" создает это предупреждение, вы не получите предупреждение для "myVector".
Поведение компилятора в случае предупреждений очень специфично для компилятора, поэтому не предполагайте, что все компиляторы работают одинаково.:)