内联变量的多重销毁
Multiple destruction of an inline variable
这是一个包含内联变量的头文件:
// 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" 两次,这是意外的。
我以为每个内联变量只有一个实例,所以我期望只有一个 "deleted".
这是编译器的错误吗?还是我做错了什么?
代码是用VS2017编译的
Is this a bug of compiler?
据我所知,是的。 GCC 和 Clang,(以及根据评论的 VS2019)只打印一次 "deleted"。
命名空间范围内的非易失性 const 内联变量具有外部链接。您描述的行为似乎暗示内部链接,这是编译器的错误行为。
为了完整起见,相关标准规则(来自最新草案,强调是我加的,括号中强调的部分是我加的):
[basic.link]
A name having namespace scope has internal linkage if it is the name of
... explicitly declared static; [does not apply] or
a non-template variable of non-volatile const-qualified type, [applies...] unless
- ...
- it is inline or exported, [exception applies] or
... A name having namespace scope that has not been given internal linkage above [applies] and that is the name of
a variable; [applies] or
...
has its linkage determined as follows:
if the enclosing namespace has internal linkage, the name has internal linkage; [does not apply]
otherwise, if the declaration of the name is attached to a named module ... [does not apply]
otherwise, the name has external linkage. [applies]
这是一个包含内联变量的头文件:
// 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" 两次,这是意外的。 我以为每个内联变量只有一个实例,所以我期望只有一个 "deleted".
这是编译器的错误吗?还是我做错了什么?
代码是用VS2017编译的
Is this a bug of compiler?
据我所知,是的。 GCC 和 Clang,(以及根据评论的 VS2019)只打印一次 "deleted"。
命名空间范围内的非易失性 const 内联变量具有外部链接。您描述的行为似乎暗示内部链接,这是编译器的错误行为。
为了完整起见,相关标准规则(来自最新草案,强调是我加的,括号中强调的部分是我加的):
[basic.link]
A name having namespace scope has internal linkage if it is the name of
... explicitly declared static; [does not apply] or
a non-template variable of non-volatile const-qualified type, [applies...] unless
- ...
- it is inline or exported, [exception applies] or
... A name having namespace scope that has not been given internal linkage above [applies] and that is the name of
a variable; [applies] or
...
has its linkage determined as follows:
if the enclosing namespace has internal linkage, the name has internal linkage; [does not apply]
otherwise, if the declaration of the name is attached to a named module ... [does not apply]
otherwise, the name has external linkage. [applies]