【问题标题】:Multiple destruction of an inline variable [duplicate]内联变量的多次破坏[重复]
【发布时间】:2019-11-04 14:47:02
【问题描述】:

这是一个包含内联变量的头文件:

// inline.hpp
#pragma once

#include <iostream>

struct Test {
    ~Test() { std::cout << "deleted" << std::endl; }
};

inline const Test test;

...包含在两个.cpp 文件中:

// usage.cpp
#include "inline.hpp"
// main.cpp
#include "inline.hpp"
auto main() -> int { return 0; }

这个程序打印了两次“deleted”,这是意料之外的。 我以为每个内联变量只有一个实例,所以我期待只有一个“已删除”。

这是编译器的错误吗?还是我做错了什么?

代码是用VS2017编译的。

【问题讨论】:

  • 其实每个cpp文件中都声明了inline全局变量。所以,你有两个对象,而不是一个。这是一个很棒的post
  • @BoBTFish 我看不出此链接有何相关性...链接已有 7 年历史,此问题与 C++17 功能有关。
  • @NutCracker 您的链接与您的评论相矛盾。链接器应该抛弃所有 TU 共享的定义,但只有一个定义。
  • 对我来说这看起来像是一个编译器错误。
  • @BoBTFish 您必须添加很多解释说明为什么“它并没有真正改变任何东西”...对我来说,它改变了一切。 extern int X; 是一个声明,inline int X; 是一个定义。在一种情况下,您需要通过 extern 声明在翻译单元中使用多个“引用”的单个定义,在其他情况下,您有多个内联定义,而不会违反 ODR(感谢 inline),但是所有定义都引用同一个对象。

标签: c++ visual-studio-2017 c++17 inline-variable


【解决方案1】:

这是编译器的错误吗?

据我所知,是的。 GCC 和 Clang,(以及根据 cmets 的 VS2019)只打印一次“deleted”。

命名空间范围内的非易失性 const 内联变量具有外部链接。您描述的行为似乎暗示了内部链接,这是编译器的错误行为。

为完整起见,相关标准规则(来自最新草案,我添加的强调,括号中的强调部分我添加):

[基本链接]

具有命名空间范围的名称如果是

的名称,则具有内部链接
  • ... 显式声明为静态; [不适用]

  • 非 volatile const 限定类型的非模板变量,[applies...] unless

    • ...
    • 它是内联或导出的,[例外适用]

...具有命名空间范围的名称,尚未在 [applies] 之上提供内部链接,即

的名称
  • 一个变量; [适用]

  • ...

其链接确定如下:

  • 如果封闭的命名空间具有内部链接,则名称具有内部链接; [不适用]

  • 否则,如果名称的声明附加到命名模块... [不适用]

  • 否则,该名称具有外部链接[适用]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-24
    • 2018-07-11
    • 2014-12-21
    • 2017-04-06
    • 1970-01-01
    • 2013-07-04
    • 2012-07-24
    相关资源
    最近更新 更多