C++ 为什么';t#pragma曾经防止多个非constexpr定义?

C++ 为什么';t#pragma曾经防止多个非constexpr定义?,c++,gcc,c++14,C++,Gcc,C++14,我刚刚花了一段时间调试了一个多定义错误,但我不清楚为什么会发生这种行为,我想了解一下 我在头文件中有类似的东西 //foo.h #pragma once my_states States[N] = {...}; 稍后,bar.h包括foo.h,因为bar.cpp具有需要了解myu状态的函数 当我为bar编写单元测试并将bar.h包含在test.cpp中时,出现了这个问题 bar.o: multiple definition of MyNamespace::named_states test.

我刚刚花了一段时间调试了一个多定义错误,但我不清楚为什么会发生这种行为,我想了解一下

我在头文件中有类似的东西

//foo.h
#pragma once

my_states States[N] = {...};
稍后,
bar.h
包括
foo.h
,因为
bar.cpp
具有需要了解
myu状态的函数

当我为
bar
编写单元测试并将
bar.h
包含在
test.cpp
中时,出现了这个问题

bar.o: multiple definition of MyNamespace::named_states
test.o: first defined here
我已通过更改为解决了此问题

constexpr my_states[n]={…}
foo.h

然而,我不明白这为什么解决了这个问题。我知道我对符号
my_states
有多个定义,这让链接器感到困惑,但如果我有一次
#pragma
保护,为什么要定义多次?我不确定为什么我需要
constexpr
限定符来表示这应该只有一个定义,据我所知,当编译程序一开始就应该阻止编译器尝试创建多个定义时。

\pragma once
只确保头文件只包含一次,它不处理代码

关于
my_states
,在没有
constexpr
的情况下,您尝试定义一个可以在运行时修改的全局变量(或类似的东西)。通过在头文件中设置其状态,实际上可以使包含此头文件的每个库实例化并包含该变量,而该变量应该是唯一定义的。。。基本上,它是一个无法编译的混乱局面。您可以在头文件中声明静态/全局变量,但应该在单个cpp文件中实例化它们


通过将
constexpr
添加到变量声明中,您可以向编译器传递在运行时无法修改的信息,而且,它的值在编译时是已知的。因此,不必担心哪个库存储/实例化它或任何类似的东西,因为它是编译时已知的绝对常量。

pragma曾经防止为一个编译单元重新包含相同的头文件,它不能跨编译单元工作。这应该分为两个独立的问题-一个是为什么constexpr修复了这个问题,另一个是为什么
#pragma once
没有。谢谢,这是有意义的。