288

クロスプラットフォームアプリケーションを使用していますが、一部の関数では、関数に渡されるすべての値が使用されているわけではありません。したがって、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
{

これはとても醜いですが、コンパイラが好む方法のようです。

または、関数の最後で変数にゼロを割り当てますか?(これは、プログラムフロー内の何かを変更して、コンパイラの警告を消音するため、嫌いです)。

正しい方法はありますか?

4

21 に答える 21

384

これを" (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);
}
于 2009-09-28T13:08:42.357 に答える
124

GCCとClangでは、__attribute__((unused))プリプロセッサディレクティブを使用して目標を達成できます。
例えば:

int foo (__attribute__((unused)) int bar) {
   return 0;
}
于 2009-09-28T13:44:16.390 に答える
90

C++17が[[maybe_unused]]属性を提供するようになりました。

http://en.cppreference.com/w/cpp/language/attributes

かなり素晴らしく、標準的です。

于 2017-05-22T07:21:46.140 に答える
43

現在の解決策が最善です。使用しない場合は、パラメーター名をコメントアウトしてください。これはすべてのコンパイラに適用されるため、GCC専用にプリプロセッサを使用する必要はありません。

于 2009-09-28T13:12:30.033 に答える
36

C++17アップデート

C ++ 17では、[dcl.attr.unused]でカバーされている属性[[maybe_unused]]を取得ます

属性トークンmaybe_unusedは、名前またはエンティティが意図的に使用されていない可能性があることを示します。これは、各属性リストに最大1回表示され、属性引数句は存在しません。..。

例:

 [[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はどちらも、 barunused_boolの両方に-Wall -Wextraを使用して診断を生成します(ライブで参照)。

[[maybe_unused]]を追加している間、診断は無音になります。

int foo ([[maybe_unused]] int bar) {
    [[maybe_unused]] bool unused_bool ;
    return 0;
}

ライブでご覧ください

C++17より前

C ++ 11では、未使用の変数をキャプチャしたラムダ式( Ben Deane経由)を使用して、マクロの代替形式を作成UNUSEDできます。

#define UNUSED(x) [&x]{}()

次の例を考えると、ラムダ式の即時呼び出しは最適化する必要があります。

int foo (int bar) {
    UNUSED(bar) ;
    return 0;
}

godboltで、呼び出しが最適化されていることがわかります。

foo(int):
xorl    %eax, %eax
ret
于 2015-07-27T13:44:01.573 に答える
29

さらにクリーンな方法は、変数名をコメントアウトすることです。

int main(int /* argc */, char const** /* argv */) {
  return 0;
}
于 2013-10-10T07:35:47.470 に答える
24

同僚が私にこの素敵な小さなマクロを教えてくれまし

簡単にするために、以下のマクロを含めます。

#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))
于 2009-11-03T20:55:55.583 に答える
24

は、デフォルトではこれらの警告にフラグを立てません。-Wunused-parameterこの警告は、コンパイラーに渡すことによって明示的にオンにされているか、パス-Wall -Wextra(または場合によっては他のフラグの組み合わせ)によって暗黙的にオンにされている必要があります。

未使用のパラメーター警告は、コンパイラーに渡すことで簡単に抑制できますが-Wno-unused-parameter、この無効化フラグは、コンパイラーのコマンドラインでこの警告の有効化フラグの後に来る必要があることに注意してください。

于 2013-10-17T16:10:41.870 に答える
15

1つ以上のパラメーターを未使用として宣言するマクロレスでポータブルな方法:

template <typename... Args> inline void unused(Args&&...) {}

int main(int argc, char* argv[])
{
    unused(argc, argv);
    return 0;
}
于 2017-01-13T14:07:01.350 に答える
8

プリプロセッサディレクティブの使用は、ほとんどの場合悪と見なされます。理想的には、害虫のようにそれらを避けたいと思います。コンパイラにコードを理解させるのは簡単であり、他のプログラマーにコードを理解させるのははるかに難しいことを忘れないでください。このような数十のケースがあちこちにあるため、後で自分自身や他の人が今すぐ読むのは非常に困難です。

1つの方法は、パラメータをある種の引数クラスにまとめることです。次に、変数のサブセット(実際には0を割り当てるのと同じ)のみを使用するか、プラットフォームごとにその引数クラスの異なる特殊化を使用できます。ただし、これは価値がない可能性があります。適合するかどうかを分析する必要があります。

不可能なテンプレートを読むことができる場合は、「例外的なC++」の本で高度なヒントを見つけることができます。あなたのコードを読む人がその本で教えられているクレイジーなものを網羅するスキルセットを手に入れることができれば、あなたは簡単に読むこともできる美しいコードを手に入れるでしょう。コンパイラーは、(前処理によってすべてを非表示にするのではなく)ユーザーが何をしているかをよく認識します。

于 2009-09-28T13:17:28.550 に答える
8

笑!私は、カオスによって破壊されたすべての異端者をこれよりもよく明らかにするSOに関する別の質問があるとは思わない!

C ++ 17に敬意を表して、 C++コアガイドラインには明確なガイドラインがあります。AFAIR、2009年に、このオプションは今日と同様に利用可能でした。そして誰かがそれがDoxygenのバグと見なされていると言うなら、Doxygenにバグがあります

于 2020-06-15T12:23:04.640 に答える
7

まず、警告はヘッダーファイルではなくソースファイルの変数定義によって生成されます。APIドキュメントを生成するためにdoxygenのようなものを使用している可能性があるため、ヘッダーは元の状態を維持できます。

ソースファイルの実装が完全に異なると仮定します。このような場合、問題のあるパラメーターをコメントアウトするか、パラメーターを書き込むことができます。

例:

func(int a, int b)
{
    b;
    foo(a);
}

これは不可解に見えるかもしれないので、UNUSEDのようなマクロを定義しました。MFCがそれを行った方法は次のとおりです。

#ifdef _DEBUG
#define UNUSED(x)
#else
#define UNUSED(x) x
#endif

このように、デバッグビルドでも警告が表示されるので、役立つ場合があります。

于 2009-09-28T14:27:34.657 に答える
7

(void)param2私は警告を黙らせる方法の代わりにこれを見ました:

void foo(int param1, int param2)
{
    std::ignore = param2;
    bar(param1);
}

これはC++11で追加されたようです

于 2019-10-04T22:26:31.520 に答える
4

パラメータ名を常にコメントアウトするのは安全ではありませんか?そうでない場合は、次のようなことができます

#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))

少し醜いです。

于 2009-09-28T13:11:10.133 に答える
4

を使用するとUNREFERENCED_PARAMETER(p)動作する可能性があります。私はそれがWindowsシステム用のWinNT.hで定義されており、gccでも簡単に定義できることを知っています(まだ持っていない場合)。

UNREFERENCED PARAMETER(p)と定義されている

#define UNREFERENCED_PARAMETER(P)          (P)

WinNT.hで。

于 2009-09-28T14:17:40.753 に答える
2

コンパイラのフラグを使用します。たとえば、GCCのフラグ: -Wno-unused-variable

于 2017-03-03T18:11:54.393 に答える
1

これはうまく機能しますが、C++11が必要です

template <typename ...Args>
void unused(Args&& ...args)
{
  (void)(sizeof...(args));
}
于 2017-03-19T17:13:44.650 に答える
1

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; }
于 2018-07-02T16:54:18.437 に答える
0

を使用__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
}
于 2016-02-10T23:56:43.613 に答える
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
于 2017-09-25T02:34:09.690 に答える
-14

警告に問題はありません。コンパイラxyがここで(正しい)警告を発行するが、これらの変数はプラットフォームzに必要であることを、メソッド/関数ヘッダーに文書化します。

警告は正しいので、オフにする必要はありません。プログラムを無効にすることはありませんが、理由があることを文書化する必要があります。

于 2009-09-28T13:11:35.043 に答える