__COUNTER__
一意の名前が必要な場合に便利です。私はこれを RAII スタイルのロックとスタックに広く使用してきました。考慮事項:
struct TLock
{
void Lock();
void Unlock();
}
g_Lock1, g_Lock2;
struct TLockUse
{
TLockUse( TLock &lock ):m_Lock(lock){ m_Lock.Lock(); }
~TLockUse(){ m_Lock.Unlock(); }
TLock &m_Lock;
};
void DoSomething()
{
TLockUse lock_use1( g_Lock1 );
TLockUse lock_use2( g_Lock2 );
// ...
}
ロックの使用に名前を付けるのは面倒です。ブロックの先頭ですべて宣言されていないと、エラーの原因になることさえあります。 lock_use4
にいるかどうかはどうやってわかりますか または lock_use11
?これは、名前空間の不必要な汚染でもあります。ロック使用オブジェクトを名前で参照する必要はありません。だから私は __COUNTER__
を使います :
#define CONCAT_IMPL( x, y ) x##y
#define MACRO_CONCAT( x, y ) CONCAT_IMPL( x, y )
#define USE_LOCK( lock ) TLockUse MACRO_CONCAT( LockUse, __COUNTER__ )( lock )
void DoSomething2()
{
USE_LOCK( g_Lock1 );
USE_LOCK( g_Lock2 );
// ...
}
しかし、私がオブジェクト ロックを呼び出したという事実にとらわれないでください。一致するペアで呼び出される必要があるすべての関数は、このパターンに適合します。特定のブロックで同じ「ロック」を複数回使用することもできます。
DEBUG マクロ以外には使用したことがありません。言えると便利です
#define WAYPOINT \
do { if(dbg) printf("At marker: %d\n", __COUNTER__); } while(0);
コンパイル時のアサーション マクロで使用して、マクロに一意の typedef の名前を作成させました。
を参照してください- C でビルド時に式をアサートする方法
血みどろの詳細が必要な場合。