Как лучше всего отключить предупреждение о неиспользуемых переменных?
У меня есть кросс-платформенное приложение, и в некоторых из моих функций не все значения, передаваемые в функции, используются. Поэтому я получаю предупреждение от GCC, сообщая мне, что есть неиспользуемые переменные.
что было бы лучшим способом кодирования вокруг предупреждения?
#ifdef вокруг функции?
#ifdef _MSC_VER
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal qrLeft, qreal qrTop, qreal qrWidth, qreal qrHeight)
#else
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal /*qrLeft*/, qreal /*qrTop*/, qreal /*qrWidth*/, qreal /*qrHeight*/)
#endif
{
Это так некрасиво, но похоже на то, как компилятор предпочел бы.
или я назначаю ноль переменной в конце функции? (который я ненавижу, потому что он меняет что-то в потоке программы, чтобы заставить замолчать предупреждение компилятора).
есть ли правильный путь?
20 ответов:
вы можете положите его в "
(void)var;" выражение (ничего не делает), чтобы компилятор видел, что он используется. Это переносится между компиляторами.например.
void foo(int param1, int param2) { (void)param2; bar(param1); }или
#define UNUSED(expr) do { (void)(expr); } while (0) ... void foo(int param1, int param2) { UNUSED(param2); bar(param1); }
в GCC и Clang вы можете использовать
__attribute__((unused))директива препроцессора для достижения вашей цели.
Например:int foo (__attribute__((unused)) int bar) { return 0; }
ваше текущее решение лучше всего-закомментируйте имя параметра, если вы его не используете. Это относится ко всем компиляторам, поэтому вам не нужно использовать препроцессор, чтобы сделать это специально для GCC.
C++17 теперь предоставляет .
http://en.cppreference.com/w/cpp/language/attributes
довольно хороший и стандартный.
коллега просто указал мне на этот милый маленький макрос здесь
для удобства я включу макрос ниже.
#ifdef UNUSED #elif defined(__GNUC__) # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) #elif defined(__LCLINT__) # define UNUSED(x) /*@unused@*/ x #else # define UNUSED(x) x #endif void dcc_mon_siginfo_handler(int UNUSED(whatsig))
еще более чистый способ-просто закомментировать имена переменных:
int main(int /* argc */, char const** /* argv */) { return 0; }
извините за такой поздний ответ.
gcc не помечает эти предупреждения по умолчанию. Это предупреждение должно быть включено либо явно путем передачи
-Wunused-parameterкомпилятору или неявно путем передачи-Wall -Wextra(или, возможно, какая-то другая комбинация флагов).неиспользуемые предупреждения параметров можно просто подавить, передав
-Wno-unused-parameterдля компилятора, но обратите внимание, что этот флаг отключения должен появиться после любых возможных флагов включения для этого предупреждения в командная строка компилятора, чтобы она могла вступить в силу.
Обновление C++17
в C++17 мы получаем атрибут [[maybe_unused]], который транслируется в [dcl.АТР.неиспользованный]
атрибут-токен maybe_unused указывает, что имя или сущность, возможно, намеренно не используется. Он должен появляется не более одного раза в каждом списке атрибутов, и никакое предложение атрибута-аргумента не должно присутствовать. ...
пример:
[[maybe_unused]] void f([[maybe_unused]] bool thing1, [[maybe_unused]] bool thing2) { [[maybe_unused]] bool b = thing1 && thing2; assert(b); }реализации не должны предупреждать этот b не используется, независимо от того, определен ли NDEBUG. -конец примера ]
для следующего примера:
int foo ( int bar) { bool unused_bool ; return 0; }и clang и gcc генерируют диагностику с помощью - Wall-Wextra как бар и unused_bool (посмотреть его в прямом эфире).
при добавлении [[maybe_unused]] молчание диагностики:
int foo ([[maybe_unused]] int bar) { [[maybe_unused]] bool unused_bool ; return 0; }Перед C++17
в C++11 альтернативная форма
UNUSEDмакрос может быть сформирован с использованием лямбда-выражения (via Ben Deane) с захватом неиспользуемой переменной:#define UNUSED(x) [&x]{}()непосредственный вызов лямбда-выражения должен быть оптимизирован, учитывая следующий пример:
int foo (int bar) { UNUSED(bar) ; return 0; }мы можем видеть в godbolt что вызов оптимизирован прочь:
foo(int): xorl %eax, %eax ret
макро-менее и портативный способ объявить один или несколько параметры как неиспользованные:
template <typename... Args> inline void unused(Args&&...) {} int main(int argc, char* argv[]) { unused(argc, argv); return 0; }
использование директив препроцессора считается злом большую часть времени. В идеале вы хотите, чтобы избежать их, как вредителей. Помните, что заставить компилятор понять ваш код легко, позволяя другим программистам понять ваш код намного сложнее. Несколько десятков таких случаев здесь и там делает его очень трудно читать для себя позже и для других прямо сейчас.
одним из способов может быть объединение ваших параметров в какой-то класс аргументов. Затем вы можете использовать только a подмножество переменных (эквивалентное вашему назначению 0 на самом деле) или имеющих разные специализации этого класса аргументов для каждой платформы. Это может, однако, не стоит, вам нужно проанализировать, будет ли это соответствовать.
Если вы можете читать невозможные шаблоны, вы можете найти дополнительные советы в книге "исключительный C++". Если бы люди, которые будут читать ваш код, могли бы получить свой набор навыков, чтобы охватить сумасшедшие вещи, преподаваемые в этой книге, тогда у вас был бы красивый код, который также может быть легко читаемым. Компилятор также будет хорошо знать, что вы делаете (вместо того, чтобы скрывать все путем предварительной обработки)
первое предупреждение определением переменной в исходном файле, а не в заголовке файла. Заголовок может оставаться нетронутым и должен, так как вы можете использовать что-то вроде doxygen для создания API-документации.
Я буду считать, что у вас есть совершенно другая реализация в исходных файлах. В этих случаях вы можете либо закомментировать оскорбительный параметр, либо просто записать параметр.
пример:
func(int a, int b) { b; foo(a); }Это может кажутся загадочными, поэтому определили макрос как неиспользуемый. То, как это сделал MFC:
#ifdef _DEBUG #define UNUSED(x) #else #define UNUSED(x) x #endifКак это вы видите предупреждение все еще в отладочных сборках, может быть полезно.
разве не безопасно всегда комментировать имена параметров? Если вы не можете сделать что-то вроде
#ifdef _MSC_VER # define P_(n) n #else # define P_(n) #endif void ProcessOps::sendToExternalApp( QString sAppName, QString sImagePath, qreal P_(qrLeft), qreal P_(qrTop), qreal P_(qrWidth), qreal P_(qrHeight))Это немного уродиной.
можно использовать
__unusedчтобы сообщить компилятору, что переменная не может быть использована.- (void)myMethod:(__unused NSObject *)theObject { // there will be no warning about `theObject`, because you wrote `__unused` __unused int theInt = 0; // there will be no warning, but you are still able to use `theInt` in the future }
С помощью
UNREFERENCED_PARAMETER(p)может работать. Я знаю, что это определено в WinNT.h для систем Windows и может быть легко определен для gcc, а также (если он еще не имеет его).
UNREFERENCED PARAMETER(p)определяется как#define UNREFERENCED_PARAMETER(P) (P)в WinNT.з.
это работает хорошо, но требует C++14 Я не знаю, можем ли мы адаптироваться к работе с C++11
template <typename ...Args> void UNUSED(Args&& ...args) { (void)(sizeof...(args)); }
В C++11, это решение я использую:
template<typename... Ts> inline void Unreferenced(Ts&&...) {} int Foo(int bar) { Unreferenced(bar); return 0; } int Foo2(int bar1, int bar2) { Unreferenced(bar1, bar2); return 0; }проверено, чтобы быть портативным (по крайней мере, на современных msvc, clang и gcc) и не производить дополнительный код, когда оптимизация включена. Без оптимизации выполняется дополнительный вызов функции и ссылки на параметры копируются в стек, но макросы не задействованы.
Если дополнительный код является проблемой, вы можете использовать вместо этого объявления:
(decltype(Unreferenced(bar1, bar2)))0;но в этот момент, макрос обеспечивает лучшую читаемость:
#define UNREFERENCED(...) { (decltype(Unreferenced(__VA_ARGS__)))0; }
я обнаружил, что большинство представленных ответов работают только для локальной неиспользуемой переменной и вызовут ошибку компиляции для неиспользуемой статической глобальной переменной.
еще один макрос, необходимый для подавления предупреждения о неиспользуемой статической глобальной переменной.
template <typename T> const T* UNUSED_VARIABLE(const T& dummy) { return &dummy; } #define UNUSED_GLOBAL_VARIABLE(x) namespace {\ const auto dummy = UNUSED_VARIABLE(x);\ } static int a = 0; UNUSED_GLOBAL_VARIABLE(a); int main () { int b = 3; UNUSED_VARIABLE(b); return 0; }это работает, потому что предупреждение не будет сообщено для нестатической глобальной переменной в анонимном пространстве имен.
C++ 11 требуется, хотя
g++ -Wall -O3 -std=c++11 test.cpp
кстати, современный C++ добавляет структурированные привязки (очень приятно!) но он (в отличие от std::tie, который поддерживает std::ignore) может быть новым источником этих предупреждений. Поэтому некоторые из этих рекомендаций могут быть полезны при использовании этой функции (мне лично нравится предложение Nampo о шаблоне и decltype, хотя это делает меня макрос грустным).
Я не вижу вашей проблемы с предупреждением. Документируйте его в заголовке метода / функции, что компилятор xy выдаст (правильное) предупреждение здесь, но что эти переменные необходимы для платформы z.
предупреждение правильно, не нужно его выключать. Это не делает недействительной программу-но она должна быть документирована, что есть причина.
Comments