如果我不使用变量,我可以跨翻译单元对它进行多个定义吗?

If I don't odr-use a variable, can I have multiple definitions of it across translation units?

本文关键字:定义 单元 翻译 变量 我可以 如果      更新时间:2023-10-16

该标准似乎暗示,如果不使用odr,则对变量的定义数量没有限制(§3.2/3):

每个

程序应只包含该程序中使用的每个非内联函数或变量的一个定义;无需诊断。

它确实说任何变量都不能在一个翻译单元中多次定义(§3.2/1):

任何翻译单元都不得包含任何变量、函数、类类型、枚举类型或模板的多个定义。

但是我在整个程序中找不到对未使用 odr 的变量的限制。那么为什么我不能编译如下内容:

// other.cpp
int x;
// main.cpp
int x;
int main() {}

使用 g++ 4.6.3 编译和链接这些文件,我收到multiple definition of 'x'的链接器错误。老实说,我期望这一点,但由于x没有在任何地方使用 odr(据我所知),我看不出标准如何限制这一点。还是未定义的行为?

您的程序违反了链接规则。 C++11 §3.5[basic.link]/9 指出:

相同

且在不同范围内声明的两个名称应表示相同 变量、函数、类型、枚举器、模板或命名空间(如果)

两个名称都有
  • 外部联系,或者两个名称都有内部链接,并在同一翻译单元中声明;和

  • 这两个名称都引用同一命名空间的成员或同一类的成员(而不是通过继承);和

  • 当两个名称都表示函数时,函数的参数类型列表是相同的;和

  • 当两个名称表示函数模板时,签名相同。

(我引用了完整的段落,供参考。 后两个项目符号在这里不适用。

在您的程序中,有两个名称x,它们是相同的。 它们在不同的范围内声明(在本例中,它们在不同的翻译单元中声明)。 这两个名称都有外部链接,两个名称都引用同一命名空间(全局命名空间)的成员。

这两个名称表示相同的变量。 声明int x;定义一个变量。 因为程序中有两个这样的定义,所以程序中有两个变量。 一个翻译单元中的名称"x"表示这些变量之一;另一个翻译单元中的名称"X"表示另一个。 因此,该程序格式不正确。

你是对的,标准在这方面有问题。 我有一种感觉,这种情况介于 3.2p1(每个翻译单元最多一个定义,如您的问题)和 3.2p6(描述类、枚举、内联函数和各种模板如何跨翻译单元具有重复定义)之间的差距。

为了进行比较,在 C 中,6.9p5 要求(我的强调):

外部

定义是外部声明,也是函数的定义 (内联定义除外)或对象。如果在表达式中使用了用外部链接声明的标识符(而不是作为结果为整数常量的sizeof_Alignof运算符的操作数的一部分),则在整个程序中的某个地方,标识符应该只有一个外部定义;否则,不得超过一个

如果标准没有说明未使用变量的定义,那么你不能暗示可能存在多个:

当这个国际 标准省略了对 行为。

因此,它可以很好地编译和运行,或者可能会在翻译过程中停止并显示错误消息,或者可能会使运行时崩溃等。

编辑:见詹姆斯麦克内利斯回答标准确实有关于它的规则。

编译没有错误,错误在于其链接。默认情况下,您的全局变量或函数对其他文件(具有extern存储)是公开的,因此在最后,当链接器想要链接您的代码时,它会看到两个x定义,并且它无法选择其中一个,因此,如果您不使用other.cpp中的main.cppx,则使它们成为静态的(这意味着仅对包含它的文件可见)

// other.cpp
static int x;
// main.cpp
static int x;