16

次のプログラムを検討してください。

#include <string>

struct S {
    S (){}

private:
    void *ptr = nullptr;
    std::string str = "";
};

int main(){}

-Weffc++これは、 GCC 4.7.1でコンパイルすると、次のように吐き出されます。

警告:「structS」にはポインタデータメンバーがあります[-Weffc ++]
警告:ただし、「S(const S&)」をオーバーライドしません[-Weffc ++]
警告:または'operator =(const S&)' [-Weffc ++]

この例のいくつかのことを除いて、これは通常は問題ありません。

  1. コンストラクター、ポインター宣言、または文字列宣言のいずれかをコメントアウトすると、警告が消えます。ポインタだけで十分だと思うので、これは奇妙ですが、そうではありません。さらに、文字列宣言を整数宣言に変更すると、それも非表示になるため、文字列(またはおそらく他の選択クラス)が含まれている場合にのみ表示されます。このような状況で警告が消えるのはなぜですか?

  2. 多くの場合、この警告は、ポインターが実行しているのが既存の変数(ほとんどの場合OSによって維持されている)を指しているときに発生します。、、newはありませんdelete。このような場合、ハンドル付きのクラスをコピーするときに、深いコピーは必要ありません。両方のハンドルが同じ内部オブジェクト(たとえば、ウィンドウなど)を指すようにします。コピーコンストラクターと代入演算子を不必要にオーバーロードしたり、警告を完全に無効にしたりせずに、コンパイラーにこれを認識させる方法はあります#pragmaか?三つのルールが適用されないのに、そもそもなぜ私は悩まされているのですか?

4

2 に答える 2

26

GCC-Weffc++にはいくつかの問題がありますが、私は使用しません。「問題」をチェックするコードは非常に単純化されているため、警告はあまりにも率直で役に立たないものになってしまいます。

その特定の警告は、 Effective C++の初版の項目 11 に基づいており、Scott は後の版でそれを (より良いものに) 変更しました。G++ コードは、実際の動的割り当てをチェックせず、ポインター メンバーの存在のみをチェックします。

第 1 版と第 3 版のガイドラインを比較する際に、 GCC の bugzillaでこの警告について私が書いたことを参照してください。

項目 11: 動的に割り当てられたメモリを持つクラスのコピー コンストラクターと代入演算子を定義します。

項目 14 に置き換え: 「リソース管理クラスでのコピー動作について慎重に考えてください」 - アドバイスは具体的ではありませんが、より有用です。しかし、それを警告に変える方法がわかりません!

于 2012-07-17T19:17:24.097 に答える
5
  1. これを行うと、POD 構造ができあがります。コンストラクターを持つことができないため、-Weffc++わざわざチェックする必要はありません。

  2. ポインターをラップする参照、shared_ptrオブジェクト、またはその他のオブジェクトを使用します。

于 2012-07-16T02:47:37.970 に答える