为什么C++的<vector>模板化类不违反一个定义规则?

Why C++'s <vector> templated class doesn't break one definition rule?

本文关键字:一个 定义 规则 vector lt C++ gt 为什么      更新时间:2023-10-16

也许这是个蹩脚的问题,但我不明白!如果我在多个翻译单元(不同.cpp)中包含<string><vector>,为什么它不会破坏ODR?据我所知,每个.cpp都是以不同的方式编译的,所以向量的方法代码将分别为每个对象文件生成,对吧?所以链接器应该检测到它并抱怨。即使它不会(我怀疑这是模板的特殊情况),当我将所有代码链接在一起时,它会在每个单元中使用一个代码或不同的克隆代码集吗???

任何模板定义都不会破坏ODR—ODR特别指出,模板定义可以在翻译单元之间重复,只要它们在字面上是重复的(而且,由于它们是重复的,因此不可能发生冲突或歧义)。

[C++14: 3.2/6]:类类型(第9条)、枚举类型(7.2)、带外部链接的内联函数(7.1.2)、类模板(第14条)、非静态函数模板(14.5.6)、类样板的静态数据成员(14.5.1.3)、类模版的成员函数(14.5.1.1)可以有多个定义,或程序中未指定某些模板参数(14.7、14.5.5)的模板专业化,前提是每个定义出现在不同的翻译单元中,并且定义满足以下要求[..]

明确允许在同一翻译单元中包含多个<vector>,并且很可能会被"#ifndef"标头保护有效地消除。

该标准对模板有一个特殊的例外,允许复制否则会违反ODR的函数(例如具有外部链接的函数和非内联成员函数)。来自C++11 3.2/5:

如果D是模板并且在多于一个翻译单元中被定义,则上述要求应同时适用于模板定义中使用的模板的封闭范围(14.6.3),以及实例化时的从属名称(14.6.2)。如果D的定义满足所有这些要求,则程序应表现为D的单一定义。如果D的定义不满足这些要求,那么行为未定义。

ODR并没有声明一个结构只会在所有编译单元中声明一次——它声明如果在多个编译单元中宣布一个结构,它必须是相同的结构。如果您有两个名称相同但内容不同的独立vector类型,则会违反ODR。在这一点上,链接器会变得混乱,你会得到混淆的代码和/或错误。