Сообщение Re[3]: Про перемещение (на примере кода) от 15.03.2025 18:54
Изменено 15.03.2025 19:06 rg45
Re[3]: Про перемещение (на примере кода)
Здравствуйте, Shmj, Вы писали:
S>
Верно.
S>
Здесь сначала происходит перемещение содержимого объекта _trackedClass в локальный объект tc. И нужно понимать, что время жизни объекта _trackedClass при этом не заканчивается. Скорлупа этого (под)объекта будет жить, пока живет его полный объект. Также примечательно, что к локальному объекту tc МОЖЕТ быть применена оптимизация NRVO. А может быть не применена — это полностью зависит от компилятора.
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 МОЖЕТ быть применена оптимизация NRVO. А может быть не применена — это полностью зависит от компилятора.
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 нет никакого. Писать просто: 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(); // <- копия НЕ порождается СТОПУДОВО!
}
То, что в этом случает не будет промежуточных копий, гарантируется стандартом языка.