Почему различное поведение показано ниже между значением lvalue и rvalue? [Дубликат]

Некоторые кодирующие снобы смотрят на них как на простое прославленное глобальное. Точно так же, как многие люди ненавидят инструкцию goto , есть другие, которые ненавидят идею когда-либо использовать глобальный . Я видел, как несколько разработчиков идут на необычные длины, чтобы избежать global , потому что они считали использование одного в качестве допуска отказа. Странно, но верно.

На практике шаблон Singleton - это всего лишь метод программирования, который является полезной частью вашего инструментария понятий. Время от времени вы можете обнаружить, что это идеальное решение, и поэтому используйте его. Но использование этого только для того, чтобы вы могли похвастаться использованием шаблона дизайна , так же глупо, как и отказаться от использования, потому что это всего лишь глобальный .

24
задан Columbo 13 March 2016 в 21:11
поделиться

2 ответа

Просто прочитайте ответ Коломбо .


Это ошибка gcc. Соответствующее правило находится в [class.temporary] :

Существует два контекста, в которых временные файлы уничтожаются в другой точке, чем конец полного выражения. [...]

Второй контекст - это когда ссылка привязана к временному. Временное, к которому привязана ссылка, или временное, являющееся полным объектом подобъекта, к которому привязана ссылка, сохраняется для времени жизни ссылки, за исключением: - временного объекта, связанного с опорным параметром в вызове функции (5.2. 2) сохраняется до завершения полного выражения, содержащего вызов. - срок жизни временной привязки к возвращаемому значению в операторе return функции (6.6.3) не продлевается; временное уничтожается в конце полного выражения в операторе return. - Временная привязка к ссылке в [new] инициализаторе (5.3.4) сохраняется до завершения полного выражения, содержащего новый инициализатор .

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

5
ответ дан Community 20 August 2018 в 11:58
поделиться
  • 1
    Будет ли эта формулировка принята? Это не последний рабочий проект. – Barry 11 March 2016 в 19:42
  • 2
    @Barry Есть несколько незначительных проблем с предложением, как есть; см. обсуждение CWG 1299 . Я очень уверен, что будет принят пересмотренный документ. Я сообщу об этом автору. – Columbo 11 March 2016 в 19:45
  • 3
    Но в 8.5.3 я полагаю, что ссылка не связана с субобъектом класса временным - см. Мой ответ. – aschepler 11 March 2016 в 19:54
  • 4
    Итак, общие замечания в 8.5.3 о инициализации ссылок не применяются? center() является AFAIK a prvalue, и я предполагаю, что подобъект a prvalue также является prvalue. Учитывая, что в этом примере нет «класса prvalue», мне кажется, что формулировка в 8.5.3 диктует создание временного double и привязки к нему вместо привязки к подобъекту-члену. – 6502 13 March 2016 в 08:34
  • 5
    @ 6502 Нет, center (). X - значение x. – Columbo 13 March 2016 в 10:32
  • 6
    @Columbo: где указано, что center().x является xvalue? В определении сказано: «X-значение является результатом определенных видов выражений, содержащих ссылки rvalue». Где ссылка rvalue в этом случае? – 6502 13 March 2016 в 11:29

Я бы утвердил ошибку в g ++, потому что, цитируя draft N3242 , §12.2 / 5:

Второй контекст - это когда ссылка привязана к временный. Временное, к которому привязана ссылка, или временное, являющееся полным объектом подобъекта, к которому привязана ссылка, сохраняется для времени жизни ссылки, за исключением:

. Таким образом, его время жизни должно быть расширенный, за исключением случаев, когда:

Временная привязка к ссылочному элементу в ctor-initializer конструктора [..]

Временная привязка к эталонному параметру в вызове функции [..]

Время жизни временной привязки к возвращаемому значению в операторе return функции [..]

Временная привязка к ссылке в new-initializer [. .]

Наш случай не соответствует ни одному из этих исключений, поэтому он должен следовать правилу. Я бы сказал, что g ++ здесь не так.

Затем, в отношении котировки aschepler, поднятой из того же проекта §8.5.3 / 5 (выделение мое):

A ссылка на тип « cv1 T1» инициализируется выражением типа « cv2 T2» следующим образом:

  1. Если ссылка является ссылкой на lvalue и выражением инициализатора a. является lvalue (но не является битовым полем), а « cv1 T1» является ссылочным-совместимым с « cv2 T2» или b. имеет тип класса ... тогда ...
  2. В противном случае ссылка должна быть ссылкой lvalue на нелетучий тип const (то есть cv1 должна быть const ), или ссылка должна быть ссылкой rvalue. а. Если выражение инициализатора i. является значением xvalue, классом prvalue, значением prvalue или значением функции lvalue и " cv1 T1" является ссылочным-совместимым с " cv2 T2" или ii. имеет тип класса ... тогда ссылка привязана к значению выражения инициализатора в первом случае .... b. В противном случае временный тип « cv1 T1» создается и инициализируется из выражения инициализатора, используя правила для неосновной копии-инициализации (8.5). Ссылка затем привязана к временному.

Глядя на то, что такое xvalue, на этот раз ссылаясь на http://en.cppreference.com/w/cpp / language / value_category ...

Выражение xvalue ("expying value") [..]

a.m, член объекта выражение, где a - значение r, а m - нестатический элемент данных не ссылочного типа;

... выражение center().x должно быть значением x, поэтому случай 2a из Применяется §8.5.3 / 5 (а не копия). Я останусь с моим предложением: g ++ ошибается.

9
ответ дан Daniel Jour 20 August 2018 в 11:58
поделиться
  • 1
    В таблице, описывающей xvalue, указано, что вызов функции, возвращающий неосновную ссылку, является prvalue. Таким образом, center() является prvalue и, я полагаю, также center().x является prvalue, а не xvalue. По-видимому, намерение состоит в том, чтобы отодвинуть xvalue только на случаи перемещения-строительства ... – 6502 13 March 2016 в 08:37
  • 2
    Я сомневаюсь, что: center() является prvalue, который является rvalue. Кроме того, x является нестационарным членом данных. Таким образом, приведенная мной часть относится. Возможно, это помогает: двойной, возвращаемый с 2.0 + 2.0, является временным, но у него нет «идентификатора»; это просто ценность. center().x также является временным двойником, но он имеет идентификатор, это один из двух элементов данных из P2d. – Daniel Jour 13 March 2016 в 08:49
  • 3
    N3242 является древним, почему вы цитируете это – M.M 13 March 2016 в 21:36
  • 4
    @ M.M Вопрос не был помечен определенным стандартом, поэтому я хотел «держать его на низком уровне». и остаться с C ++ 11 (который также ввел понятие xvalue, так) – Daniel Jour 13 March 2016 в 21:40
  • 5
    Предпочтительно использовать C ++ 14 draft (N4140), если нет причин использовать C ++ 11 специально; с тех пор было исправлено множество дефектов – M.M 13 March 2016 в 22:04
Другие вопросы по тегам:

Похожие вопросы: