命名空间中的全局变量 - 线程中的值不同

5
考虑以下情况:
  • 使用boost::asio创建了2个不同的网络端口,每个端口都在自己的线程中运行
  • 一个端口用于接收和处理数据 - class DataConnection包装在std::thread
  • 另一个端口用于发送统计信息 - class StatConnection也包装在std::thread

为了计算连接数(以及其他小数据片段),我的想法是在namespace内部使用static变量,如下所示:

#include <atomic>

namespace app {
 namespace status {
   static std::atomic<long> counter = 0; 
 }
}

这对于类很有效。在这里,我在c'tor中递增并查看值的增加。
但是,我的类中的计数器始终为0。
为什么会发生这种情况?
我尝试了一些替代方法:
  • 将>交换为:没有任何区别。
  • 使用没有静态关键字的命名空间。
然后我得到了链接器错误:
multiple definition of `app::status::searchtime'
./src/status/Status.o:/[...]/include/status/Status.hpp:16: first defined here
[...]

那么为什么不同的线程中count的值会不同呢?

什么?命名空间的静态成员?为什么不直接使用类的静态成员呢? - Griwes
该类仅存在短时间,boost::asio相关的类通过std::thread启动n次。因此,我认为将其放入命名空间中可以使其分离。但是静态成员可能会解决问题,我会进一步研究。我仍然不确定为什么命名空间方法没有奏效。 - kei1aeh5quahQu4U
1个回答

10

static在命名空间中引入内部链接,因此每个翻译单元将拥有自己的counter副本,这与您实际想要的相反!

请改用在头文件中使用extern

//foo.h:
#include <atomic>

namespace app {
    namespace status {
        extern std::atomic<long> counter;
    }
}

一个 翻译单位中定义变量:

//foo.cpp:
#include "foo.h"

namespace app {
    namespace status {
        std::atomic<long> counter{0L};
    }
}

1
为了让它与 std::atomic<long> 协同工作,我不得不在 foo.cpp 中编写:std::atomic<long> counter(0); - kei1aeh5quahQu4U
@emteh:啊,我不知道构造函数是否是显式的。我会进行编辑,谢谢。 - ildjarn
你能解释一下在这个上下文中 "extern" 关键字的含义吗? - JonaFane
1
@JonaFane:在这个上下文中,它是一个存储类别说明符,并且在那里是必要的,以便使头文件中的app::status::counter成为一个_声明_而不是一个_定义_ - ildjarn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接