Подтвердить что ты не робот

Почему нет предупреждений gcc/g++ для неиспользуемых временных рядов?

Рассмотрим следующий код:

void ListenerImpl::attach(boost::shared_ptr<ISubscriber> subscriber)
{
    boost::unique_lock<boost::mutex>(mtx);
    subscribers.push_back(subscriber);
}

void ListenerImpl::notify(MsgPtr msg)
{
    boost::unique_lock<boost::mutex>(mtx);

    //notify all subscribers
    BOOST_FOREACH(boost::shared_ptr<ISubscriber> subscriber, subscribers){
        subscriber->update(msg);
    }

}

(Это реализация шаблона наблюдателя, как описано в GoF.) Здесь вмешательство пользователя заключалось в том, чтобы защитить функции attach() и notify() от одновременного запуска, следовательно, boost:: unique_lock. Цель заключалась в защите контейнера subscribers.

Но действительно очень сложно заметить, что блокировки на самом деле являются только временными (присмотритесь, нет имен, назначенных для них). Таким образом, блокировка мьютекса будет немедленно освобождена, когда временное разрушено, то есть код не является потокобезопасным. Я бы ожидал в таких ситуациях, как предупреждение о компиляторе. Что-то вроде "Неиспользуемый временный".

Хуже того, cppcheck тоже не признает эту ошибку. (cppcheck: инструмент анализа кода c/С++ http://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=Main_Page)

Gcc выдает предупреждения о неиспользуемых переменных. Временная здесь неиспользуемая переменная, и, безусловно, результат невнимательности программиста. Итак, почему в подобных случаях нет предупреждений? Может быть, слишком сложно обнаружить такие ситуации?

4b9b3361

Ответ 1

Компилятор не выдает предупреждение, так как вполне возможно, что вы можете обновлять некоторую переменную static-member / global внутри конструктора (что является действительным и значимым). например:.

struct A
{
  static int count;
  A () { count ++; }
};

Теперь, когда вы просто вызываете временное:

A();

В случае, если такого обновления не происходит, компилятор не выкопает конструктор A и не проверяет, произошло ли что-то полезное. Он всегда считается допустимым сценарием. Можно отметить много таких случаев, связанных с временными.

Ответ 2

Обратите внимание, что ваше предлагаемое предупреждение будет также выдано для каждого it++;, которое встречается во многих циклах.

iammilind уже упомянул, что иногда это намерение создать и немедленно уничтожить temp: когда есть побочные эффекты.

И в мета-программировании шаблонов можно создать и уничтожить временное, на всякий случай, если пользователь поставляет класс с побочными эффектами. Если для создания шаблона используется простой класс без побочных эффектов, предупреждения будут отображаться глубоко в коде шаблона.

Поэтому в предлагаемом предупреждении будет много ложных срабатываний. Трудно найти настоящие предупреждения среди ложных.

Поэтому я ожидаю, что производители компиляторов решили, что их время лучше потрачено в другом месте.

Ответ 3

hmm.. Я не уверен, но не может ли это быть защищено с помощью обычного С++ тоже?

class Mutex;
class Lock {
    Lock(Mutex *mutex);
};

int main() {
    Lock /* lock */ (&mtx);
    return 0;
}

Я получаю это предупреждение компилятора при компиляции с DJGPP:

C:\df>gxx -c a.cpp
a.cpp: In function 'int main()':
a.cpp:8:30: error: 'mtx' declared as reference but not initialized

Он компилируется отлично, если я раскомментирую "блокировку" и добавляю переменную mutex.

Итак, если ваша переменная "mtx" является указателем. Что произойдет, если вы измените его и передадите его как "& mtx".