4

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

// 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编译。

4

1 回答 1

5

这是编译器的错误吗?

据我所知,是的。GCC 和 Clang(以及根据评论的 VS2019)仅打印一次“已删除”。

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

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

[基本.链接]

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

  • ... 明确声明为静态的;[不适用]

  • 非 volatile const 限定类型的非模板变量,[应用...] 除非

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

...具有名称空间范围的名称尚未在[applies]上方提供内部链接,并且是

  • 一个变量; [适用]

  • ...

其联系确定如下:

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

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

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

于 2019-11-04T14:55:39.167 回答