Почему я не могу сделать инициализированный в классе `const const std :: string` статическим членом

У меня есть следующий рабочий код:

#include <string>
#include <iostream>

class A {
public:
const std::string test = "42";
//static const std::string test = "42"; // fails
};

int main(void){
A a;
std::cout << a.test << '\n';
}

Есть ли веская причина, почему нельзя сделать тест static const ? Я понимаю, до c ++ 11 это было ограничено стандартом. Я думал, что c ++ 11 ввел инициализацию в классе, чтобы сделать его немного более дружественным. Я также не такой семантический для целочисленного типа доступен с давних пор.

Конечно, это работает с внеклассовой инициализацией в форме const std::string A::test = "42";

Я думаю, что если вы можете сделать это нестатичным, то проблема заключается в одном из двух. Инициализация его вне класса (обычно constсоздаются в процессе создания объекта). Но я не думаю, что это проблема, если вы создаете объект, независимый от любых других членов класса. Второй имеет несколько определений для статического члена. Например. если бы он был включен в несколько .cpp файлы, приземляющиеся в несколько объектных файлов, а затем компоновщик будет иметь проблемы при связывании этих объектов вместе (например, в один исполняемый файл), так как они будут содержать копии одного и того же символа. Насколько я понимаю, это в точности соответствует ситуации, когда кто-то предоставляет внеклассное право в соответствии с объявлением класса в заголовке, а затем включает этот общий заголовок в более чем одном месте. Насколько я помню, это приводит к ошибкам компоновщика.

Однако теперь ответственность за это перекладывается на пользователя / программиста. Если кто-то хочет иметь библиотеку с static они должны предоставить определение вне класса, скомпилировать его в отдельный объектный файл, а затем связать все другие объекты с этим, следовательно, имея только одну копию двоичного определения символа.

Я читаю ответы в Нужно ли нам отдельно определять статические члены, даже если они инициализируются внутри определения класса? а также Почему я не могу инициализировать неконстантный статический член или статический массив в классе?.

Я все еще хотел бы знать:

  1. Это только стандартная вещь, или за этим стоит более глубокая аргументация?
  2. Может ли это быть обойти с constexpr и пользовательский
    литеральные механизмы. И clang, и g ++ говорят, что переменная не может иметь не-литеральный тип. Может быть, я могу сделать один. (Может по какой-то причине это тоже плохая идея)
  3. Действительно ли такая большая проблема для компоновщика, чтобы включить только одну копию
    символ? Так как это static const все должно быть бинарно-точным
    неизменные копии.

Просьба также прокомментировать, если я что-то упустил или неправильно понял.

8

Решение

Ваш вопрос вроде состоит из двух частей. Что говорит стандарт? А почему так?

Для статического члена типа const std::string, он должен быть определен вне спецификатора класса и иметь одно определение в одной из единиц перевода. Это является частью правила «Одно определение» и определено в пункте 3 стандарта C ++.

Но почему?

Проблема заключается в том, что объекту со статической продолжительностью хранения требуется уникальное статическое хранение в конечном образе программы, поэтому его необходимо связать из одного конкретного блока перевода. Спецификатор класса не имеет дома в одной единице перевода, он просто определяет тип (который должен быть одинаково определен во всех единицах перевода, где он используется).

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

Однако сложный тип, как std::string, при статической длительности хранения нужно хранение, даже если они const, Это потому, что им может потребоваться динамическая инициализация (вызов их конструктора перед входом в main).

Можно утверждать, что компилятор должен хранить информацию об объектах со статической продолжительностью хранения в каждой единице перевода, где они используются, и затем компоновщик должен объединить эти определения во время компоновки в один объект в образе программы. Мое предположение, почему это не сделано, состоит в том, что это потребует слишком много информации от компоновщика.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]