Является ли элемент массива rvalue (элемент получен с использованием выражения индекса) rvalue? [Дубликат]

Так как это самый популярный вопрос в отношении этой проблемы, я снова опубликую здесь еще один ответ:

Похоже, что есть более простой способ сделать это (но только в MySQL):

select *
from (select * from mytable order by id, rev desc ) x
group by id

Пожалуйста, прокомментируйте ответ пользователя Bohemian в на этот вопрос за предоставление такого краткого и элегантного ответа на эту проблему.

EDIT: хотя это решение работает для многих людей, оно может быть нестабильным в долгосрочной перспективе, поскольку MySQL не гарантирует, что оператор GROUP BY вернет значимые значения для столбцов, не входящих в список GROUP BY. Поэтому используйте это решение на свой страх и риск

15
задан stackcpp 15 July 2015 в 18:02
поделиться

2 ответа

Насколько я могу судить, вы действительно правы, это выглядит как «ошибка» , хотя, честно говоря, это недавно изменилось с дефектом CWG 1213 , в котором говорится:

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

, и это изменило раздел 5.2.1 [expr.sub] следующим образом:

Постфиксное выражение, за которым следует выражение в квадратных скобках - постфиксное выражение. Одно из выражений должно иметь тип «массив Т» или «указатель на Т», а другой должен иметь неперечисленное перечисление или интегральный тип. Результатом является lvalue типа «T». Тип «T» должен быть полностью определенным типом объекта.62 Выражение E1 [E2] идентично (по определению) к * ((E1) + (E2)) [ Примечание: см. 5.3 [expr.unary] и 5.7 [expr.add] для получения подробных сведений о * и + и 8.3.4 [dcl.array] для получения подробной информации о массивах. -End note], за исключением того, что в случае операнда массива результат равен lvalue, если этот операнд является lvalue и xvalue иначе.

Так что действительно результат f().a[0]; и static_cast<S&&>(s).a[0] должны быть x значениями.

У этого дефекта не было предлагаемой резолюции до декабря 2012 года, а поддержка отчета о дефектах clangs перечисляет поддержку этого отчета о дефектах как неизвестную, поэтому, скорее всего, разработчики не получили исправления

Обновить

Подано сообщение об ошибке clang : Оператор подстроки, примененный к временному массиву, приводит к lvalue .

2
ответ дан Shafik Yaghmour 26 August 2018 в 20:04
поделиться

Я могу проверить в Clang 3.4.1 std = c ++ 11.

Вот мои выводы:

int i = f().a[0] будет верным: вы получаете ссылку на временная структура, время жизни временного увеличивается на длительность ссылки, вы принимаете значение: fine.

int *i = &f().a[0] принимается компилятором. Тем не менее, предупреждение f о том, что вы возвращаете ссылку на локальный временный объект , имеет смысл здесь. Время жизни временного объекта увеличивается на время ссылки: здесь время для копирования адреса. Как только вы берете адрес a, содержащий объект исчезает, и у вас есть только оборванная ссылка .

int *i = f().a - это точно такой же случай, как и предыдущий.

Но когда вы делаете &f().a, вы принимаете адрес rvalue типа 'int [3]' , и нет смысла брать такой адрес : вы можете использовать только его значение.

Давайте перейдем еще дальше:

S s = f(); верен. Вы получаете ссылку на временную структуру, время жизни временного расширения на длительность ссылки, вы принимаете значение: fine.

Теперь &s.a[0] является четко определенным указателем на int , as is int *ix2 = &static_cast<S&&>(s).a[0];

Вы даже можете записать: int (*ix3)[3] = &s.a;, чтобы принять адрес массива до 3 int, но по той же причине вы не можете написать &static_cast<S&&>(s).a, потому что вы адрес rvalue типа 'int [3]'

TL / DR

С S s = f(); s.a является четко определенным значением r, s.a[0] является корректным значением lvalue (вы можете написать s.a[0] = 5;).

f().s является rvalue, но с его помощью будет вызываться UB, потому что он заканчивается ссылкой на временный объект, который будет быть уничтожен, прежде чем вы сможете его использовать.

f().s[0] может использоваться как хорошо определенное значение rvalue. Вы можете использовать его как lvalue, но по той же причине, что и выше, он будет вызывать UB.

0
ответ дан Serge Ballesta 26 August 2018 в 20:04
поделиться
Другие вопросы по тегам:

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