静态成员变量读取不一致

问题描述 投票:0回答:1

我想定义可以在不同文件中打开和关闭的计时器,而无需考虑必须在哪里声明它们以及它们的范围应该是什么。所以我选择使用包装在带有内联静态变量的类中的全局变量,并且该类由计时器的名称模板化:

#include <chrono>
#include <algorithm>

template<size_t N>
struct StringLiteral 
{
    constexpr StringLiteral(const char (&str)[N]) {std::copy_n(str, N, value);}
    char value[N];
};

template<StringLiteral>
struct GlobalTimer
{
    inline static std::chrono::system_clock::time_point startTime = std::chrono::system_clock::now();
    inline static double totalTime = 0;

    inline static void on()
    {
        startTime = std::chrono::system_clock::now();
    }
    inline static void off() 
    {
        auto endTime = std::chrono::system_clock::now();
        totalTime += std::chrono::duration<double>(endTime - startTime).count();
    }
    inline static double get()
    {
        return totalTime;
    }
};

在实践中我这样使用它们:

GlobalTimer<"myFirstTimer">::on();
//do some stuff
GlobalTimer<"myFirstTimer">::off();
//eventually in another file
std::cout << "myFirstTimer : " << GlobalTimer<"myFirstTimer">::get() << std::endl;

但是,有一个问题我无法理解。在我的多文件代码中,这个

get()
函数始终返回 0,而当我在较小的示例上尝试时它会起作用。此外,当我在
std::cout << totalTime << std::endl
函数的 return 语句之前添加
get()
时,计时器开始工作并且不再返回 0。所以我以为是编译器优化问题,但是我尝试在debug中编译,用gcc和clang,结果是一样的。现在我认为这可能是一种未定义的行为,所以我来这里是为了了解真相:)。

[编辑]

为了消除字符串文字唯一性的不确定性,我尝试了以下方法:

constexpr char myFirstTimer[10] = "myFirstTimer";

GlobalTimer<myFirstTimer>::on();
//do some stuff
GlobalTimer<myFirstTimer>::off();
//in the same file this time
std::cout << "myFirstTimer : " << GlobalTimer<myFirstTimer>::get() << std::endl;

这并不能解决问题,它返回0...

c++ static
1个回答
0
投票

事实上,当您创建

GlobalTimer<"myFirstTimer">
的实例时,它会生成不同的类型,即每种类型的每个静态成员和函数。

模板参数应使用

typename
class
关键字,或者是整数。

可能(因为它的 UB)在你的情况下指针被视为数字(地址),为每个新地址创建不同的类型。

这里是解释:传递 const char* 作为模板参数

© www.soinside.com 2019 - 2024. All rights reserved.