クロスプラットフォームアプリケーションを使用していますが、一部の関数では、関数に渡されるすべての値が使用されるわけではありません。そのため、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
{
これはとてもいですが、コンパイラが好む方法のようです。
または、関数の最後に変数にゼロを割り当てますか? (これは、コンパイラの警告を黙らせるためにプログラムフロー内の何かを変更しているため、嫌いです)。
正しい方法はありますか?
「(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は[[maybe_unused]]
属性を提供するようになりました。
http://en.cppreference.com/w/cpp/language/attributes
とても素敵で標準的。
gcc は、デフォルトではこれらの警告にフラグを立てません。この警告は、-Wunused-parameter
をコンパイラーに明示的に渡すか、-Wall -Wextra
(または他のフラグの組み合わせ)を暗黙的に渡すことでオンにする必要があります。
未使用のパラメータ警告は、-Wno-unused-parameter
をコンパイラに渡すことで簡単に抑制できますが、この無効フラグは、コンパイラコマンドラインでこの警告の有効フラグを有効にした後に有効にする必要があることに注意してください。
同僚が私にこの素敵な小さなマクロを教えてくれました here
簡単にするために、以下のマクロを含めます。
#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;
}
C++ 17では、属性を取得します[[maybe_unused]][dcl.attr.unused]
属性トークンmaybe_unusedは、名前またはエンティティが意図的に使用されていない可能性があることを示します。それは各属性リストに最大で一度だけ現れ、属性引数節は存在してはならない。 ...
例:
[[maybe_unused]] void f([[maybe_unused]] bool thing1, [[maybe_unused]] bool thing2) { [[maybe_unused]] bool b = thing1 && thing2; assert(b); }
NDEBUGが定義されているかどうかにかかわらず、実装はbが使用されていないことを警告するべきではありません。 —例の終了]
次の例:
int foo ( int bar) {
bool unused_bool ;
return 0;
}
Clangとgccは両方とも-Wall -Wextraを使用して診断を生成しますbarおよびunused_bool( ライブで見る )。
[[maybe_unused]]を追加すると、診断が無音になります。
int foo ([[maybe_unused]] int bar) {
[[maybe_unused]] bool unused_bool ;
return 0;
}
ライブで見る 。
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
1つ以上パラメータを未使用として宣言するマクロレスで移植可能な方法:
template <typename... Args> inline void unused(Args&&...) {}
int main(int argc, char* argv[])
{
unused(argc, argv);
return 0;
}
ほとんどの場合、プリプロセッサディレクティブの使用は悪と見なされます。理想的には、害虫のようにそれらを避けたいです。コンパイラーにコードを理解させるのは簡単であり、他のプログラマーにコードを理解させることははるかに難しいことを忘れないでください。ここやこのような数十のケースでは、後で自分で読んだり、今すぐ他の人に読んだりすることは非常に困難です。
1つの方法は、パラメーターを何らかの引数クラスにまとめることです。その後、変数のサブセットのみ(実際に0を割り当てることに相当)を使用するか、プラットフォームごとにその引数クラスの異なる専門化を行うことができます。ただし、これには価値がない場合があるため、適合するかどうかを分析する必要があります。
不可能なテンプレートを読むことができる場合は、「Exceptional C++」ブックで高度なヒントを見つけることができます。あなたのコードを読む人が、その本で教えられているクレイジーなものを自分のスキルセットに取り込むことができれば、簡単に読むことができる美しいコードを手に入れることができます。コンパイラーは、(前処理によってすべてを隠すのではなく)何をしているのかをよく知っているでしょう
最初に、ヘッダーファイルではなくソースファイルの変数定義によって警告が生成されます。 APIドキュメントを生成するためにdoxygenのようなものを使用している可能性があるため、ヘッダーはそのままの状態であり続ける必要があります。
ソースファイルの実装がまったく異なると仮定します。このような場合は、問題のあるパラメーターをコメント化するか、単にパラメーターを書き込むことができます。
例:
func(int a, int b)
{
b;
foo(a);
}
これは不可解に思えるかもしれないので、UNUSEDのようなマクロを定義しました。 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))
ビットさが少ない。
UNREFERENCED_PARAMETER(p)
を使用すると動作します。 WindowsシステムのWinNT.hで定義されており、gccでも簡単に定義できることを知っています(まだ持っていない場合)。
UNREFERENCED PARAMETER(p)
は次のように定義されます
#define UNREFERENCED_PARAMETER(P) (P)
winNT.hで.
__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
}
コンパイラのフラグを使用します、例えばGCCのフラグ:-Wno-unused-variable
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; }
これはうまく機能しますが、C++ 11が必要です
template <typename ...Args>
void unused(Args&& ...args)
{
(void)(sizeof...(args));
}
提示された回答のほとんどは、ローカルの未使用変数に対してのみ機能し、未使用の静的グローバル変数に対してコンパイルエラーが発生することがわかりました。
未使用の静的グローバル変数の警告を抑制するために必要な別のマクロ。
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