Сообщение Re[3]: Про перемещение (на примере кода) от 15.03.2025 18:54
Изменено 15.03.2025 19:10 rg45
Re[3]: Про перемещение (на примере кода)
Здравствуйте, Shmj, Вы писали:
S>
Верно.
S>
Здесь сначала происходит перемещение содержимого объекта _trackedClass в локальный объект tc. И нужно понимать, что время жизни объекта _trackedClass при этом не заканчивается. Скорлупа этого (под)объекта будет жить, пока живет его полный объект. Также примечательно то, что объект tc является move eligible. Это означает, что, если к нему не будет применена NRVO, то к нему будет применено ещё одно перемещение. Т.е. либо NRVO (что скорее всего), либо второе перемещение, копирования точно не будет.
Как бы то ни было, хотя бы одного перемещения здесь не избежать. Поэтому смысла в этом локальном объекте tc нет никакого. Писать просто: return std::move(_trackedClass); Так и код проще, и потенциальное число перемещений меньше.
S>
Строго говоря, здесь копия может порождаться, а может нет. Стандарт языка не регламентирует число промежуточных копий, это implementation specifics. Но, если NRVO таки было подключено, что скорее всего, тогда никаких дополнительных копий не будет.
К счастью, этот пример можно легко видоизменить так, чтоб вместо необязательной NRVO применялась обязательная RVO:
То, что в этом случает не будет промежуточных копий, гарантируется стандартом языка.
S>
S> TrackedClass take() {
S> return _trackedClass; // <- тут копия порождается.
S> }
S>};
S>
Верно.
S>
S> TrackedClass take() {
S> TrackedClass tc = std::move(_trackedClass); // <- Копия не порождается.
S> return tc;
S> }
S>};
S>
Здесь сначала происходит перемещение содержимого объекта _trackedClass в локальный объект tc. И нужно понимать, что время жизни объекта _trackedClass при этом не заканчивается. Скорлупа этого (под)объекта будет жить, пока живет его полный объект. Также примечательно то, что объект tc является move eligible. Это означает, что, если к нему не будет применена NRVO, то к нему будет применено ещё одно перемещение. Т.е. либо NRVO (что скорее всего), либо второе перемещение, копирования точно не будет.
Как бы то ни было, хотя бы одного перемещения здесь не избежать. Поэтому смысла в этом локальном объекте tc нет никакого. Писать просто: return std::move(_trackedClass); Так и код проще, и потенциальное число перемещений меньше.
S>
S>TrackedClass fun1() {
S> Wrapper w = Wrapper();
S> TrackedClass t = w.take(); // <- копия НЕ порождается.
S> return t;
S>}
S>
Строго говоря, здесь копия может порождаться, а может нет. Стандарт языка не регламентирует число промежуточных копий, это implementation specifics. Но, если NRVO таки было подключено, что скорее всего, тогда никаких дополнительных копий не будет.
К счастью, этот пример можно легко видоизменить так, чтоб вместо необязательной NRVO применялась обязательная RVO:
TrackedClass fun1() {
Wrapper w = Wrapper();
return w.take(); // <- копия НЕ порождается СТОПУДОВО!
}
То, что в этом случает не будет промежуточных копий, гарантируется стандартом языка.
Re[3]: Про перемещение (на примере кода)
Здравствуйте, Shmj, Вы писали:
S>
Верно.
S>
Здесь сначала происходит перемещение содержимого объекта _trackedClass в локальный объект tc. И нужно понимать, что время жизни объекта _trackedClass при этом не заканчивается. Скорлупа этого (под)объекта будет жить, пока живет его полный объект. Также примечательно то, что объект tc является move eligible. Это означает, что, если к нему не будет применена NRVO, то к нему будет применено ещё одно перемещение. Т.е. либо NRVO (что скорее всего), либо второе перемещение, копирования точно не будет.
Как бы то ни было, хотя бы одного перемещения здесь не избежать. Поэтому смысла в этом локальном объекте tc нет никакого. Лучше писать просто:
Так и код проще, и потенциальное число перемещений меньше.
S>
Строго говоря, здесь копия может порождаться, а может нет. Стандарт языка не регламентирует число промежуточных копий, это implementation specifics. Но, если NRVO таки было подключено, что скорее всего, тогда никаких дополнительных копий не будет.
К счастью, этот пример можно легко видоизменить так, чтоб вместо необязательной NRVO применялась обязательная RVO:
То, что в этом случает не будет промежуточных копий, гарантируется стандартом языка.
S>
S> TrackedClass take() {
S> return _trackedClass; // <- тут копия порождается.
S> }
S>};
S>
Верно.
S>
S> TrackedClass take() {
S> TrackedClass tc = std::move(_trackedClass); // <- Копия не порождается.
S> return tc;
S> }
S>
Здесь сначала происходит перемещение содержимого объекта _trackedClass в локальный объект tc. И нужно понимать, что время жизни объекта _trackedClass при этом не заканчивается. Скорлупа этого (под)объекта будет жить, пока живет его полный объект. Также примечательно то, что объект tc является move eligible. Это означает, что, если к нему не будет применена NRVO, то к нему будет применено ещё одно перемещение. Т.е. либо NRVO (что скорее всего), либо второе перемещение, копирования точно не будет.
Как бы то ни было, хотя бы одного перемещения здесь не избежать. Поэтому смысла в этом локальном объекте tc нет никакого. Лучше писать просто:
TrackedClass take() { return std::move(_trackedClass); }
Так и код проще, и потенциальное число перемещений меньше.
S>
S>TrackedClass fun1() {
S> Wrapper w = Wrapper();
S> TrackedClass t = w.take(); // <- копия НЕ порождается.
S> return t;
S>}
S>
Строго говоря, здесь копия может порождаться, а может нет. Стандарт языка не регламентирует число промежуточных копий, это implementation specifics. Но, если NRVO таки было подключено, что скорее всего, тогда никаких дополнительных копий не будет.
К счастью, этот пример можно легко видоизменить так, чтоб вместо необязательной NRVO применялась обязательная RVO:
TrackedClass fun1() {
Wrapper w = Wrapper();
return w.take(); // <- копия НЕ порождается СТОПУДОВО!
}
То, что в этом случает не будет промежуточных копий, гарантируется стандартом языка.