Продолжение никак не могу понять DR 712

Это в основном продолжение моего предыдущего вопроса о DR 712. Позвольте мне сначала объяснить, почему я настаиваю на том, чтобы посмотреть на что-то это можно было бы считать старым стандартом C++11, но моя проблема в том, что раздел [basic.def.odr] уже трудно понять в C++11, и я хочу полностью охватить его, прежде чем углубляться в тот же раздел в текущем проекте, который, на мой взгляд, еще сложнее.

Ответ на мой предыдущий вопрос от Austing Hastings был отличным, но у меня все еще есть один маленький момент, который не ясен. в [basic.def.odr]/2 в C++11. Рассмотрим этот маленький и очень простой пример:

const int i = 1;
int main()
{
    int j = i;
}

Из [basic.def.odr]/2 в C++11 i не odr-used в int j = i;, поскольку i — это объект, который удовлетворяет требованию появления в постоянном выражении и lvalue-to-rvalue преобразование немедленно применяется к i. Для меня это не имеет особого смысла, так как i явно используется в объявлении int j = i;, что можно увидеть в слегка измененном коде, показанном здесь, где я отключил оптимизацию переменной i из скомпилированного кода.

Конечно, в моих рассуждениях выше должно быть что-то неправильное, потому что я не верю, что C++11 может быть неверным в таком простом примере. Опять же, чего мне сейчас не хватает???


person João Afonso    schedule 01.03.2017    source источник
comment
Все, что нужно в вашем примере кода, — это значение i. Это означает, что его можно оптимизировать, и ему не требуется выделенное хранилище.   -  person Cheers and hth. - Alf    schedule 01.03.2017


Ответы (1)


Я пытаюсь перевести свое понимание стандартного «используемого» и «использованного правила определения» на что-то более интуитивное здесь. Термины, отличные от «используемый» и «используемый 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
comment
Спасибо за исчерпывающий ответ (+1) - person João Afonso; 01.03.2017