5

printf()usingへのすべての呼び出しを削除できます#define printf。のようなデバッグ出力がたくさんある場合はどうすればよいstd::cout << x << endl;ですか? cout <<プリプロセッサを使用して単一ファイル内のステートメントをすばやくオフにするにはどうすればよいですか?

4

7 に答える 7

10

「巻き戻し」が既に述べたように、迅速な解決策は何もしないストリームです。ただし、より良い実装があります。

class NullStream {
    public:
    NullStream() { }
    template<typename T> NullStream& operator<<(T const&) { return *this; }
};

これは 3 つのトークンのシーケンスであるため、まだわずかな問題があり、個別にstd::cout再定義する必要はありません。簡単な解決策はstdcout

#ifdef NDEBUG
    #define COUT std::cout
#else
    #define COUT NullStream()
#endif

COUT << "Hello, world" << std::endl;
于 2009-09-07T14:09:06.623 に答える
6

一般的な原則として、stdout へのログ記録は避けるべきです。ログファイルにログを記録する方がはるかに優れています。その後、標準の構成ツールを使用してログ レベルを変更したり、完全にオフにしたりできます。

ちょうど私の$ 0.02.....

于 2009-09-07T14:03:06.057 に答える
5

デバッグ出力ステートメントを次のように置き換えます。

IFDBG(cout << result << endl);

次に、それに応じてマクロを定義できます。

#ifdef DEBUG
#  define IFDBG(x) x
#else
#  define IFDBG(x)
#endif
于 2009-09-07T13:58:27.820 に答える
4

このマクロを定義します:

#ifdef DEBUG
    #define MY_LOG std::cout
#else
    #define MY_LOG if(false) std::cout
#endif

このマクロの利点は、コンパイラの最適化にあります

これらの IF 内に配置された式がコンパイル時に定数で決定可能である場合、コンパイラがコードからそれらを既に削除していることはほぼ確実です... https://stackoverflow.com/a/14657645/5052296

于 2015-08-06T21:58:26.103 に答える
4

NullStream は、デバッグ ステートメントをすばやく削除する方法を探している場合に適したソリューションです。ただし、デバッグ用に独自のクラスを作成することをお勧めします。これは、より多くのデバッグ機能が必要な場合に必要に応じて拡張できます。

class MyDebug
{
    std::ostream & stream;
  public:
    MyDebug(std::ostream & s) : stream(s) {}
#ifdef NDEBUG
    template<typename T>
    MyDebug & operator<<(T& item)
    {
      stream << item;
      return *this;
    }
#else
    template<typename T>
    MyDebug & operator<<(T&)
    {
      return *this;
    }
#endif
};

これは、最初に必要なことを実行できる単純なセットアップであり、デバッグ レベルなどの機能を追加できるという追加の利点があります。

更新: マニピュレータは関数として実装されているため、マニピュレータも受け入れたい場合 (endl) を追加できます:

MyDebug & operator<<(std::ostream & (*pf)(std::ostream&))
{
  stream << pf;
  return *this;
}

そして、すべてのマニピュレータ タイプに対して (すべてのマニピュレータ タイプに対してオーバーロードする必要がないように):

template<typename R, typename P>
MyDebug & operator<<(R & (*pf)(P &))
{
  stream << pf;
  return *this;
}

通常の関数ポインタも受け入れるため、この最後のものには注意してください。

于 2009-09-07T15:09:18.437 に答える
3

cerrおそらく、何もしないという名前のインスタンスを使用して、新しいストリームのようなクラスを定義するプリプロセッサ ハックを実行できます。本当に運が良ければ、コンパイラは関数が何もしないことを認識し、operator<<()out の呼び出しを最適化します。

何かのようなもの

class NullStream
{
public:
  NullStream();

  NullStream& operator<<(const std::string& text) { return *this; }
  // And operators for other types, too
}
static NullStream cerr;

ただし、これは非常にハックです。ソースを調べて、ログの適切なサポートを追加する方が (はるかに) 優れています。

于 2009-09-07T14:01:48.050 に答える
0

置き換えるマクロを定義することはcout、VCS にアップロードする必要はありませんが、デバッグ中に一時的に行うだけであれば、その役割を果たしていると思います。coutしたがって、次のostream(0)ように置き換えることができます

#ifdef NDEBUG
#define cout ostream(0).flush()
#endif

このように、 と plain の両方で動作し、をstd::cout含む場合に使用できます。a への書き込みはノーオペレーションです。関数呼び出しは、それへの非 const 参照を取得するように行われます (したがって、出力などに使用される非メンバーにもバインドされます)。その型はであるため、 とまったく同じように動作する必要があります。coutostream<iostream>ostream(0)flushoperator<<std::stringostreamcout

于 2009-09-07T23:51:54.750 に答える