14

Visual Studioでは、RAIIの目的でのみオブジェクトを使用することがよくあります。例えば:

ScopeGuard close_guard = MakeGuard( &close_file, file );

close_guardの全体的な目的は、関数の終了時にファイルが閉じられるようにすることであり、他の場所では使用されません。ただし、Visual Studioは、「ローカル変数は初期化されていますが、参照されていません」という警告を表示します。この特定のケースでは、この警告をオフにします。

このような状況にどのように対処しますか?Visual Studioは、このオブジェクトは役に立たないと考えていますが、重要なデストラクタがあるため、これは間違っています。

正当な理由があってもこの警告をオフにするので、これに#pragma警告ディレクティブを使用したくありません。

4

12 に答える 12

9

オブジェクトに重要なデストラクタがある場合、Visual Studio はその警告を表示しません。次のコードは、VS2005 で警告をまったく生成しません (/W4)。


class Test
{
public:
    ~Test(void) { printf("destructor\n"); }
};

Test foo(void) { return Test(); }

int main(void)
{
    Test t = foo();
    printf("moo\n");

    return 0;
}

デストラクタをコメントアウトすると、警告が表示されます。コードはそのままではありません。

于 2008-10-20T20:34:11.827 に答える
6

方法1:#pragma warningディレクティブを使用します。

#pragma warningコンパイラの警告メッセージの動作を選択的に変更できます。

#pragma warning( push )
#pragma warning( disable : 4705 ) // replace 4705 with warning number

ScopeGuard close_guard = MakeGuard( &close_file, file );

#pragma warning( pop )

このコードは現在の警告状態を保存し、次に特定の警告コードの警告を無効にしてから、最後に保存された警告状態を復元します。

方法2:次のような回避策を使用します。Visual Studioは幸せになり、あなたも幸せになります。この回避策は、多くのMicrosoftサンプルや他のプロジェクトで使用されています。

ScopeGuard close_guard = MakeGuard( &close_file, file );
close_guard;

#defineまたは、警告を回避するためのを作成できます。

#define UNUSED_VAR(VAR) VAR
...
ScopeGuard close_guard = MakeGuard( &close_file, file );
UNUSED_VAR(close_guard);

一部のユーザーは、ScopeGuardがtypedefであるため、提示されたコードは機能しないと述べました。この仮定は間違っています。

http://www.ddj.com/cpp/184403758

C ++標準によれば、一時値で初期化された参照は、その一時値を参照自体の存続期間中存続させます。

于 2008-10-20T20:29:22.850 に答える
3

を使用しております:

static_cast<void>(close_guard);

コンパイラが文句を言っている変数の場合。

于 2008-10-20T20:30:44.173 に答える
3

この場合、マクロをずっと使用します。

#define SCOPE_GUARD(guard, fn, param) \
    ScopeGuard guard = MakeGuard(fn, param); \
    static_cast<void>(guard)

これであなたのコードは素敵で短くなりました:

SCOPE_GUARD(g1, &file_close, file1);
SCOPE_GUARD(g2, &file_close, file2);

このアプローチの利点の 1 つは、後で必要に応じて など を追加して__LINE____func__ガード アクションをログに記録できることです。

于 2008-10-20T23:19:11.663 に答える
3

一部の VC++ ヘッダー ファイルでは、MS がマクロを定義しています。

#define UNUSED(x) x

次のように使用されます:

ScopeGuard close_guard = MakeGuard( &close_file, file );
UNUSED(close_guard);

警告を黙らせ、それを文書化します。

于 2008-10-20T20:31:30.893 に答える
2

この場合、ScopeGuard は実際には参照型に対する typedef です。残念ながら、これは機能しません。

その場合、デストラクタが呼び出されないため、ScopeGuard全体が機能しないことを意味しませんか???

于 2008-10-20T20:37:09.590 に答える
1

使用することによってのみ、そのコード行の周りに #pragma 警告のスコープを設定できます

#pragma warning(push)
#pragma warning(disable:XXXX)
your code here;
#pragma warning(pop)

また

#pragma warning(disable:XXXX)
your code here;
#pragma warning(default:XXXX)

UNREFERENCED_PARAMETER(close_guard);上記のコード行の後に使用することもできます。

于 2008-10-20T20:31:24.560 に答える
1

実際には、#pragma disable ... または「UNUSED」をしぶしぶ使用すると思います。ただし、基本的なルールとして、余分な量を犠牲にしても、コードに警告が表示されないようにする必要があります。異なるプラットフォームおよびオペレーティング システム上の複数の異なるコンパイラで、警告なしでコンパイルする必要があります。そうでない場合は、コードを修正して修正する必要があります。gcc -Wall レベルで警告を生成するコードを維持することはお勧めできません。

コンパイラの警告はあなたの友人であり、問​​題または原則として注意する必要があります。それが意味する場合でも、少しかさばり、より冗長な方法で実装する必要があります。コードが移植され、維持され、永久に存続するため、長期的には元が取れます...

于 2008-10-20T20:40:24.323 に答える
0

ScopeGuard宣言に「volatile」を追加してみてください。

于 2008-10-20T20:27:59.747 に答える
0

上記のsminkの投稿を使用し、#defineの横にコメントを貼り付けることを追加するだけです

于 2008-10-20T20:35:02.400 に答える
0

ScopeGuardImpl1 オブジェクトを明示的に作成できますが、使用しているケースで結果が判読できないほど多くのパラメーターがない場合に限ります。そうすれば、VS警告が明らかに失敗する参照初期化ウィズテンポラリーを回避できます。コストは、MakeGuard テンプレート マジックを取得するのではなく、手書きで説明する必要があることです。

于 2008-10-20T22:47:55.283 に答える
-3

ここでの中心的な問題は、コンパイラがあなたが何をしようとしているのかを完全に理解していないようです...これは、変数が使用されていない場合でも、変数の割り当てが解除されたときに呼び出されるコードを取得するために、C++ でスコープ セマンティクスを使用しているようです。 . 右?そのメカニズム自体は境界線として私を襲います...コンパイラは未使用の変数を削除する権利を持っているはずですが、C ++の構築セマンティクスはこれらのものを本当に台無しにします。手先の早業ではない、これを行う他の方法はありませんか?

于 2008-10-20T20:35:21.060 に答える