Множественное уничтожение встроенной переменной

Вот заголовочный файл, содержащий встроенную переменную:

// 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; }

Эта программа дважды печатает "удалено", что является неожиданным. Я думал, что существует только один экземпляр каждой встроенной переменной, поэтому я ожидал только одного "удаленного".

Это ошибка компилятора? Или я что-то не так сделал?

Код скомпилирован с VS2017.

1 ответ

Решение

Это ошибка компилятора?

Насколько я могу судить, да. GCC и Clang (а также VS2019 согласно комментариям) печатают "удалено" только один раз.

Энергонезависимая встроенная переменная const в области пространства имен имеет внешнюю связь. Поведение, которое вы описываете, похоже, подразумевает внутреннюю связь, что является неправильным поведением компилятора.

Для полноты изложения соответствующие стандартные правила (из последнего проекта, выделено мной, выделенные части, добавленные мной, заключены в скобки):

[basic.link]

Имя, имеющее область пространства имен, имеет внутреннюю связь, если это имя

  • ... явно объявленный статический; [не применяется] или

  • нешаблонная переменная энергонезависимого константного типа, [применяется...], если

    • ...
    • он встроен или экспортируется, [применяется исключение] или

... Имя, имеющее область пространства имен, для которого не была указана внутренняя связь выше [применяется], и это имя

  • Переменная; [применяется] или

  • ...

связь определяется следующим образом:

  • если охватывающее пространство имен имеет внутреннюю связь, имя имеет внутреннюю связь; [не применяется]

  • в противном случае, если объявление имени прикреплено к именованному модулю... [не применяется]

  • в противном случае имя имеет внешнюю связь. [применяется]

Другие вопросы по тегам