gpt4 book ai didi

C++ 自动实现的函数和 ODR

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:02:55 27 4
gpt4 key购买 nike

详细解释如下,问题在底部。

我的问题具体指的是当前的 C++ 标准草案(也是当前的“主要”标准)here .更具体地说,关于成员函数和 ODR,第 3.2 节第 6 点(第 35 页)指出 D 的每个定义应包含相同的标记序列

最近在项目中添加新的数据分析时遇到了如下问题。

我正在写一个文件,A.cpp。我创建了一个小的虚拟结构来保存一些数据。在此示例中,我将其称为 Data

namespace Example {
struct Data {
//etc
};
//Use Data
};

但是在另一个文件 B.cpp 中,Example 命名空间中已经有一个名为 Data 的结构。编译器为这两个类生成 Data::~Data();,然后调用它们各自成员的析构函数。 B.cpp 中的定义包含一个 vector ,当使用 A.cpp 中定义的布局调用 Data 结构时,该 vector 被破坏时会导致爆炸。虽然这两个结构似乎都能正常工作,没有编译时错误,但似乎在链接时链接器会选择一个定义并使用它,而忽略另一个定义。 (因此导致 A.cpp 内的 Data 对象爆炸)

在 GCC 或 MSVC 下都没有发出警告。 启用优化后,问题不会发生(函数是内联的,没有链接时间困惑)。

我的问题是,标准只声明行为是未定义的如果 D 是一个模板并且在多个翻译单元中定义。要么我误解了标准,允许未定义的行为悄悄发生;或者 GCC 和 MSVC 都默默地接受他们不应该接受的东西(并且应该拒绝产生输出或发出警告)(当前情况是未定义和不一致的行为,没有诊断)。

有人可以帮我理解这与类中未定义的函数定义的冲突有何不同(这确实会导致警告/错误)。

最佳答案

Could someone please help me understand how this is different to conflicting definitions of functions that are not defined in classes (which do cause warnings/errors).

不同之处在于类内的函数定义在名义上是隐式内联,如果再次遇到该函数,它会抑制编译器警告。这并不意味着编译器必须内联它们——它可能会决定使用任何启发式方法而不去打扰,或者它可能简单地从不在某些优化级别内联。无论如何,如果您链​​接的代码看到了名义上内联非成员函数的不同定义,那么您会遇到完全相同的问题。

见 3.2/6

There can be more than one definition of a class type ... in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements.

— each definition of D shall consist of the same sequence of tokens; and

[others requirements]

更一般地说,您应该将您的代码放入匿名命名空间...它们旨在防止此类跨翻译单元问题。

关于C++ 自动实现的函数和 ODR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20470369/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com