Я пытаюсь перевести свое понимание стандартного «используемого» и «использованного правила определения» на что-то более интуитивное здесь. Термины, отличные от «используемый» и «используемый ODR», не предназначены для использования в качестве стандартных терминов, определенных ниже.
Что-то, используемое ODR, в основном означает, что «нам нужно, чтобы это имело идентичность». Обычно это означает, что кто-то берет ссылку или указатель на него.
Если вам нужно только значение чего-то, это не всегда делает его используемым для ODR. Значение константы времени компиляции не требует идентификации.
В С++ идентификатор в основном означает, что «у него действительно должно быть где-то хранилище».
В стандарте не сказано, что «это ODR используется, если нам нужно, чтобы у него была идентичность», потому что тогда разные компиляторы будут иметь разные правила для определения того, нужна ли им идентичность. Например, если операция встроена, а ссылка пропущена, значит ли это, что ей больше не нужна идентификация?
Таким образом, стандарт описывает, что означает «используемое ODR», и отличает его от используемого значения.
int j = i;
для этого не нужна личность i
. Ему просто нужно его значение. const int i = 1;
имеет значение, которое не может (при определенном поведении) измениться.
int const* pj = &i;
для этого действительно нужна идентификация. Два разных указателя на i
должны согласовать расположение i
по стандарту.
void foo( const int& x ) {
int j = x;
}
foo(i);
Это также требует идентификации для i
. Берем ссылку на i
. Несмотря на то, что единственное, что мы делаем, — это просто ссылка на ее значение, (краткое, теоретическое) существование этой ссылки означает, что у нее есть идентичность.
const int a = 3; const int b = 4;
int i = (a<2)?a:b;
недостаток заключался в том, что для этого требовалось, чтобы a
и b
имели идентичность (они использовали ODR-использование), потому что взаимодействие ?
с используемыми правилами. Дефект говорил: «Мы должны исправить это».
Ссылка на DR 712
И после этого разрешения для этого выражения требуется только значение a
и b
, а не их идентификатор, поэтому им не нужно иметь хранилище.
Нас заботит, есть ли у чего-либо хранилище, потому что вещи, требующие хранения, должны иметь уникальную точку определения. В принципе, они не могут существовать только в заголовочном файле.
Обратите внимание, что со встроенными переменными в C++17 нас это может меньше волновать; в соответствии с правилом «как если бы» созданное встроенное хранилище может быть стерто из существования, если никто на самом деле не обращает внимания на личность. Поскольку функции, принимающие const&
, могут «случайно» навязывать требования к идентичности для вещей, предназначенных для использования только в качестве токенов, это хорошее ослабление правил.
person
Yakk - Adam Nevraumont
schedule
01.03.2017
i
. Это означает, что его можно оптимизировать, и ему не требуется выделенное хранилище. - person Cheers and hth. - Alf   schedule 01.03.2017