2016-06-20 12 views
16
#include <vector> 

class Object 
{ 
}; 

int main() 
{ 
    Object myObject; 
    std::vector<int> myVector; 
} 

コンパイラが発する:オブジェクトstd :: vectorが宣言されていても使用されていないときにコンパイラが警告を出さないのはなぜですか?

myVectorなし警告を。どうして?これを有効にする方法はありますか?

+2

C++では、コンストラクタとデストラクタは重要なロジックを含むことができます。したがって、一般的には、一見未使用の変数宣言を実際に排除できるかどうかは決定できません。 – pyon

+1

Objectにゼロパラメータのないコンストラクタを追加すると、警告が表示されますか? – lorro

答えて

20

任意のオブジェクトが宣言されている(したがって初期化され、ある時点で破棄される)かどうかは、目に見える副作用が一般的に判断できないかどうか。コンストラクタは、その定義がコンパイラに知られていない関数を呼び出すことであったり、外部状態や問題を確定できないような他のアスペクトに依存することもあります。

最初のケースでは、コンストラクタは(宣言されていなくても)自明で、デストラクタと同じです。 Objectにはメンバーが含まれていないので、実際には何もしないことは明らかであり、容易に検出できます。Object foo std::vector

は非自明なデストラクタと共に(定義知られていないかもしれない(new ...外部状態+機能))メモリを割り当てることができる非自明なコンストラクタ(その定義は知られていない外部状態+機能を有しています(delete ...))。この場合、宣言を削除するのが安全かどうかを推論することで(このようにして警告する必要があるという警告を出すことはできません)、コンパイラは宣言をコードに残す必要があります。理由)。

よくある例はstd::lock_guardです。これは、構築時にミューテックスをロックし、破壊されたときに自動的にロックを解除するために使用されます。したがって、オブジェクトが有効範囲内にある限り、ミューテックスは保持されます。一般的には、std::lock_guardオブジェクトには全くアクセスしませんが、宣言しておくと便利です。これは職場でのRAII原則です。

このような場合に警告を発することは、警告を消す人々につながる迷惑になり、警告が役に立たなくなります。コンパイラは、最適化中に宣言を削除した場合にのみ警告を出すような方法で設計されていても、特定の最適化が有効な場合に警告が表示される理由もあります)。

6

この警告簡単な型に対してのみ生成されます。コンパイラは、コンストラクトが外部関数を呼び出すかどうかを見つけることはできません。 Objectクラスにコンストラクタを追加すると、コンパイラは警告も発行します。 GCCはこの警告を生成する必要がありますタイプにタグを付けることができます、あなたが__attribute__((warn_unused))を使用してこの操作を行うことができます。

http://coliru.stacked-crooked.com/a/0130c8ef29c121a1

例:

class __attribute__((warn_unused)) Object 
{ 
    public: 
    Object(){} 
    void use() {} 
}; 

int main() 
{ 
    Object myObject; // will give : warning: unused variable 'myObject' [-Wunused-variable] 
    //myObject.use(); // uncomment to hide this warning 
} 

[編集]

gccの属性ページから:https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html

warn_unused一般的でないコンストラクタや デストラクタを持つC++型では、この型の変数 が本当に使われていないかどうかをコンパイラが判断することは不可能です。この のtype属性は、 の基本型の変数と同様に、この型の変数には が使用されていないと警告されるべきであることをコンパイラに通知します。この属性は、ちょうど がstd :: stringのような値を表す型に適しています。 のリソースを制御するタイプ(std :: lock_guardなど)では適切ではありません。

この属性もCでは使用できますが、C にはコンストラクタまたはデストラクタがないため、この属性は不要です。

+1

libstdC++は、この属性でほとんどの型をマークする必要がありますか?代わりに、ロックやそれに類する型の属性no_warn_unusedをデフォルトで設定する必要がありますか? –

+2

@MarcGlisあなたは正しいです(私はlibstdC++の99%をマークすることを意味します)。これに関するオープンな議論があります:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55203。 – marcinj

+1

私はMarcに同意します。これはデフォルトの動作でなければなりません。 – Jovini

2

上記の回答と同様に、コンパイラのドキュメントも確認してください。いくつかのコンパイラは、同じ警告を何度も表示しないように設定できます。 "myObject"の宣言をコメントアウトすると、 "myVector"と同じ警告が表示されます。 "mObject"がその警告を最初に生成すると、 "myVector"の警告は表示されません。

警告の場合のコンパイラの動作はコンパイラ固有のものなので、すべてのコンパイラが同じように動作するとは仮定しないでください。 :)

関連する問題