Используется ли в cppreference термин «идентичность [объекта]» в двух разных значениях для c ++ 11 и для c ++ 17? - PullRequest
5 голосов
/ 24 октября 2019

Я думал, что мне удалось полностью понять (с помощью других вопросов SO, спасибо) изменения в C ++ 17, касающиеся категорий значений, но теперь я заметил эту проблему, которая говорит о том, что я на самом деле не понимаю их.

В C ++ 11 существовала интерпретация категорий значений «имеет идентичность / может быть перемещена из», и определение того, что означает «идентичность», все еще присутствует в cppreference :

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

В C ++ 17 «имеет идентичность / может быть перемещен из» больше не соответствует действительности, но новое определение также основано на концепции «идентичности»:

glvalue («обобщенное» lvalue) - это выражение, оценка которого определяет идентичность объекта, битового поля или функции;

Мой вопрос / ошибкаПонимание: это то же самое значение «идентичности», или это другая «идентичность»? Насколько я понимаю, ситуация в c ++ 17 выглядит следующим образом:

A f() { return A(); }

A a = f(); // 1: f() is a prvalue expression, used to directly initialize a.
f();       // 2: f() is a prvalue expr., converted to xvalue by temporary materialization
A&& r = f(); // 3: f() is a prvalue expr., converted to xvalue by temporary materialization

Во 2-м и 3-м случае я получаю xvalue, что означает, что он должен иметь тождество. Поэтому я должен иметь возможность получить его адрес [отредактировано:] Я должен быть в состоянии определить, относится ли он к той же сущности, что и какое-либо другое выражение, но я не думаю, что смогу. Конечно, в третьем случае я могу выполнить «& r» как отдельную команду, а затем сравнить ее адрес с адресом другого выражения, но это потому, что A && является lvalue. Является ли взятие адреса через A &&, что в данном случае означает «получен прямо или косвенно»? Я предположил, что это не может быть правильным ответом, потому что в C ++ 11 я также легко могу сделать

A&& r = f(); // 4: f() is a prvalue expression. Temporary materialization does
             // not happen, the temporary (prvalue) gets its lifetime 
             // extended to match the lifetime of the reference
&r;

, и все же объект, на который ссылается r, все еще является временным, несмотря на то, что его время жизни увеличено, и вВременные значения c ++ 11 являются частными. Поэтому я предполагаю, что только того факта, что я могу связать с ним A && (из которого, как и любое lvalue, я могу взять адрес, но только в отдельном выражении) недостаточно, чтобы сделать вывод, что его оценка определяет идентичность (в конце концов, что бы ни происходило встрока «& r;» не является частью оценки моего исходного выражения), и все же в c ++ 17 мне кажется, что это будет единственно возможная интерпретация?

Можете ли вы помочь мне, определивкакая часть того, что я написал, неверна? Или это правильно, и ответ прост: слово «идентичность» изменило свое значение?

1 Ответ

3 голосов
/ 26 октября 2019

Почему вы думаете, что концепции C ++ 11 больше не применяются? На странице говорится, что эта версия представила идею «имеет идентичность», а не то, что это единственная версия, которая ее использует. В C ++ 17 было сказано, что prvalues ​​«ждут, пока» они используются для инициализации объекта, чтобы вообще стать объектом. (Следовательно, он объединяет «быть объектом» и «иметь идентичность», что проще; очевидно, каждый объект может иметь this, который можно обнаружить.)

Что на самом деле означает, что адрес этого целевого объектанезаметно передается на место строительства prvalue, так что он появляется в правильном месте с самого начала. Компиляторы уже делали это под именем RVO, но изменение гарантировало это и устраняло формальные ограничения на подвижность.

xvalue, безусловно, имеет идентичность: если вы передаете prvalue в функцию по ссылке (любого типа),он может взять свой адрес. Он может даже вернуть его, чтобы (во время того же полного выражения) созданная им функция могла использовать свой адрес. Запрет на использование адреса временного является отдельной мерой безопасности, которая применяется даже после (скажем) использования static_cast<A&&>(get_a()) для принудительной временной материализации. (Тем не менее, это не может помешать вам получить адрес glvalue, который ссылается на временное значение, возвращаемое другой функцией.)

...