我的需求是统计程序整个运行过程中程序中每个for语句循环的总次数,例如:
int for_counter_1 = 0;
int for_counter_2 = 0;
void f() {
for (int i = 0; i < 10; i++, for_counter_2++) {
// ...
}
}
int main() {
for (int i = 0; i < 10; i++, for_counter_1++) {
f();
}
printf("%d\n", for_counter_1); // should output: 10
printf("%d\n", for_counter_2); // should output: 100
}
由于我的程序中有大量的for循环(一些密码算法),并且我将继续扩展它,所以我考虑使用宏来实现带有自己的循环计数器的for语句,如下所示:
#define CONCAT_INNER(a, b) a ## b
#define CONCAT(a, b) CONCAT_INNER(a, b)
#define FOR_COUNTER() CONCAT(for_counter_, __LINE__)
#define for_with_counter(...) \
static int FOR_COUNTER() = 0; \
for (__VA_ARGS__, ++FOR_COUNTER())
void f() {
for_with_counter(int i = 0; i < 10; ++i) {
// ...
}
}
int main() {
for_with_counter(int i = 0; i < 10; ++i) {
f();
}
}
它可以为每个for循环生成一个静态计数器
for_counter_N
,其中N代表循环所在的行号。我可以在调试环境中看到这个循环发生的总次数。但是,由于它们是局部静态变量,因此我无法在程序末尾的主函数中将它们全部打印出来。
有什么办法可以实现我的目的吗?它不一定是宏,而且由于我使用的是 C++,如果我可以使用模板等来解决它就好了。或者如果有一个调试工具可以做到这一点也可以。
使用全局
map
计数器,并结合 __FILE__
和 __LINE__
作为键(例如 std::pair<std::string_view, int>
键)。
模板功能似乎更好:
extern std::/*unoredered_*/map<std::string_view, std::size_t> loop_counters; // put definition in cpp file.
// F callable which return false to stop the loop
template <typename F>
void for_with_counter(std::string_view loop_name, int begin, int end, F f) {
auto& counter = loop_counters[loop_name];
for (int i = begin; i != end; ++i) {
++counter;
if constexpr (std::is_same_v<void, decltype(std::invoke(f, i))>) {
std::invoke(f, i);
} else {
if (!std::invoke(f, i)) {
return;
}
}
}
}
随着使用
for_with_counter("my_loop", 0, 10, [/*..*/](int i){ /* .. */ });