【问题标题】:C++ create a counter macros increasing along all filesC ++创建一个计数器宏沿所有文件增加
【发布时间】:2023-03-16 11:12:01
【问题描述】:

我正在尝试定义一个随着我项目的所有源文件增加的宏。与 __COUNTER__ 宏不同,它对所有文件都是独立的。 我尝试在类中使用静态成员变量,例如:

class A{
static int GetNextNum() {
 number++;
 return number - 1;
}
private:
  static int number;
};
#define NEXT_NUM A::GetNextNum()

但结果不是我想要的。例如,我希望在这个循环中的每次迭代都有相同的数字(就像__COUNTER__ 一样):

for (int i = 0; i < 10; ++i) {
  doSomething(NEXT_NUM)
}

虽然我已经实施了它,但它在每次迭代中都会增加。关于如何实现我需要的任何想法? (我正在使用 Visual Studio,但更喜欢独立于编译器的解决方案)。

编辑:按照这里的要求,这是一个类似于我想做的事情的简约示例。我尝试定义一个类来计算我通过代码的给定部分的次数。以下是我将如何使用这样的类:

for (int i = 0; i < 10; ++i) {
  ExecuteCounter(location_id);
  ... do stuff ...
}

我还在析构函数中记录并积累了大量其他内容,但我相信这足以让您了解这个想法。起初,我使用了一个映射,其中 entry 是一个对象,我在其中存储我关心的信息,字符串是通过将__FILE____LINE__ 附加来形成的(从而唯一地标识了位置),但事实证明这很慢。因此,我决定在其中使用表格和索引,而不是使用地图。这将从整体复杂性中去除对数并显着提高性能。希望这个解释能让我的问题更清楚。

【问题讨论】:

  • 我正在为我创建的代码中的每个位置创建一个单独的类实例。我通过使用将索引('COUNTER')映射到实际对象的表来实现这一点。除此之外,我也是出于好奇。
  • 请发布您要解决的问题的最小、完整示例。 必须有更好的方法。

标签: c++ macros


【解决方案1】:

这样简单的事情就足够了吗?

#include <stdio.h>
int g_counter = 0;   // make it visible to other files through 'extern'
#define UPDATE_COUNTER()   {\
                        static int _this_counter_ = 0;\
                        if (_this_counter_ == 0) {\
                           g_counter++;\
                           _this_counter_ = 1;\
                        }\
                     }\
int main() {
   printf("Counter: %d\n", g_counter);
   for (int i=0; i<100; i++) {
      UPDATE_COUNTER();
   }
   printf("Counter: %d\n", g_counter);
   for (int i=0; i<100; i++) {
      UPDATE_COUNTER();
   }
   printf("Counter: %d\n", g_counter);
}

您可以通过在头文件中声明 g_counter 并将其包含在所有源文件中来使 g_counter 对其他文件可见。同样的标头也是 UPDATE_COUNTER 宏的好地方。

【讨论】:

  • 我不得不稍微修改你的代码,让 UPDATE_COUNTER 在第一次迭代时将 g_counter 的值(当 _this_counter 为 0 时)存储在另一个静态变量中,但它让我知道了如何解决我的问题。谢谢。
【解决方案2】:

所以我知道您希望有一个计数器来记录您在代码中访问某个位置的次数。

这种事情的基本思想应该很简单,首先你的宏应该扩展为一个静态变量的声明,每次你访问这个地方都会递增。

static size_t my_count = 0;
++my_count;

如果您没有多线程,就可以解决问题。 (如果有,请查看新的原子操作)。

现在,您还希望在某处可以访问计数的最终结果。使用您自己的collector 类型的另一个static 变量最容易做到这一点,它接收您的计数器的地址和一些用于命名约定的应用程序字符串作为构造函数的参数。

#define DO_ACCOUNTING(NAME)                       \
do {                                              \
  static size_t my_count L = 0;                   \
  static collector my_collector(&my_count, #NAME);\
  ++my_count;
} while(0)

do-while 的内容只是将这些变量设置为范围,这样您就不会污染您的命名空间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-27
    • 1970-01-01
    • 1970-01-01
    • 2018-09-18
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    相关资源
    最近更新 更多