Информация об изменениях

Сообщение Re[3]: Про перемещение (на примере кода) от 15.03.2025 18:54

Изменено 15.03.2025 18:57 rg45

Re[3]: Про перемещение (на примере кода)
Здравствуйте, Shmj, Вы писали:


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. А может быть не применена — это полностью зависит от компилятора.

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 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(); // <- копия НЕ порождается СТОПУДОВО!
}


То, что в этом случает не будет промежуточных копий, гарантируется стандартом языка.