Pull to refresh

Comments 17

Вроде все понятно, а вроде не особо. Самое непонятное, насколько необходимо в этом разбираться.
rvalue помогают избавиться от лишних копирований объектов. Т.е. можно передать параметром в функцию какой-то объект и поместить его в контейнер без копирования объектов. Имеет смысл так заморачиваться во время обработки больших объемов данных. Когда копирование занимает драгоценное время.

std::vector<std::string> strings;
void addString(std::string &&string) {
  strings.emplace_back(std::move(string));
}

addString(std::string("hello world!"));

Чуть подробнее в документации к std::vector::emplace_back.
Как раз emplace_back с мув-семантикой связан слабо. Он просто конструирует объект прямо в векторе, и в данном случае разницы между emplace_back и push_back не будет, в обоих случаях вызовется мув-конструктор.

Слегка разница будет: аргумент push_back всегда T, то есть будет создана копия при вызове метода, а вот само это значение будет move-нуто в вектор. Если же созжания объекта до его непосредственного положения в векторе надо избежать, достаём emplace с параметрами конструктора (в том числе move-конструктора).

Можете поподробнее про «всегда T»? Судя по спецификации и здравому смыслу, push_back может принимать T&& (что в данном случае и будет происходить), а потом вызовется мув конструктор для T уже в векторе. То есть копирования не произойдет, я так считаю.
Для себя я пришел к выводу, что для комфортной работы с плюсами достаточно понимать lvalue и rvalue. Остальное, по факту, промежуточные категории для удобного объяснения тех или иных моментов в стандарте.
И всё же нет. Ну то есть если вам пофиг на оверхеды или вы надеетесь что компилятор вам всё сам соптимизирует, то можно. Если же не хотите, чтобы ваш софт выполнял кучу лишних копирований, либо просто читаете чей-то код, где автор этого не хотел, то без rvalue-ссылок вам не обойтись. Хотя официальную терминологию со всеми этими xvalue я даже не пытался запомнить.

Вот ещё статья более понятная про это всё habr.com/ru/post/322132
Хм. Так rvalue я все-таки указал. Я имел в виду, что из перечисленных в статье (и, соответственно, в стандарте) терминов в повседневном программировании наиболее важны только два. А ссылки на rvalue, move-семантика, perfect forwarding, вот это вот всё — разумеется, важно, т.к. имеет строго прикладной характер.
Так перечисленные в статье новые термины наполовину нужны как раз для того чтобы поведение rvalue-ссылок описать. Названия естественно помнить не обязательно, а вот без знания сути этих понятий (пусть и без названий) оперировать rvalue-ссылками грамотно не получится.
Всё зависит от того, насколько часто вы читаете Стандарт, и как часто сообщения компилятора ставят вас в тупик. Если редко, то наверно необходимости особой нет. А, ну ещё вариант — если вы разрабатываете компилятор — тогда точно необходимо. :)
по идее могут спросить на собеседовании :-)

разработчику библиотек желательно понимать, т.к. нужно обеспечить movable поведение.

в разных непонятных ситуациях, когда код на вид вполне нормален, а компилятор ругается. понимание, что нельзя присваивать rvalue и главное сообразить, что это rvalue — сократит время исправления ошибки.

в общем нужно, но тяжеловато. пока читаешь — более менее понятно. навскидку в обычной жизни — лезешь проверять в справочник.

интересно, а компилятор может выдать информацию, какие выражения к какому типу относятся ??

Компилятор занят синтактическим , а не семантическим анализом ) Обычно его ругань более явная "нельзя привязать А к Б"

Через https://cppinsights.io/ кое что можно прояснить,

Но хотелось бы не гадать на стандарте, а точно знать что компилятор думает о той или иной конструкции

Битовые поля – удобный инструмент для низкоуровнего программирования, однако, их реализация несколько выпадает из общей структуры категорий выражений. 

В то же время, взять адрес битового поля или инициализировать им неконстантную ссылку не получится.

Второе утверждение верно, а первое не совсем. Когда речь идет об identity,имеется в виду любой вид уникальности. В Си++ ставится различие между storage (область памяти) и memory location (ячейка памяти).Ряд объектов обладает и тем и другим, например, объекты скалярного типа или члены классов и элементы массивов этого типа. У класса есть область памяти, но нет ячейки, в то время как члены могут занимать ячейки. У ссылок в составе классов и у битовых полей (которые по определению являются членами класса) есть ячейка памяти, но нет области памяти. Уникальной особенностью битовых полей является то, что несколько полей ненулевого размера могут занимать одну ячейку

Скорее в уникальную ситуацию можно было бы записать члены объединения, т.к. тут перекрываются области памяти. Однако нам категорически запрещено рассматривать объединение как два или более объектов существующих одновременно. И это как раз из-за того, что система категорий фундаментальна.

Указатель и ссылка обращаются к области памяти. Поэтому для битовых полей их и не может быть. Поэтому невозможна ссылка на ссылку. Однако ВСЯ ячейка памяти целиком является субъектом выражения, поэтому, если а и b - битовые поля с общей ячейкой, то результат выражения a++ + ++b является таким же неопределенным поведением как и a++ + ++a , где одно и то же значение (одна и та же ячейка) меняется дважды.

Не кажется ли мне, что это и есть причина существования системы категорий? В противном случае вся эти правила покажется нелогичным собранием ограничений, и непонятно накой и, главное, зачем они были так написаны?

Sign up to leave a comment.

Articles