move семантика до 11 стандарта

379
02 февраля 2017, 01:47

Как поместить в data_new объект data_old без копирования последнего, т.е. переместить его? Стандарт 98.

Data foo() {
    Data data_old;
    //...
    return data_old;
}
int main() {
    Data data_new = foo();
}
Answer 1

Использовать оптимизацию не ниже -O1 и полагаться на copy elision — конструирование объекта прямо на области стека для data_new.

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

struct Foo {int a;};
Foo bar(int a)
{
    Foo result;
    result.a = a;
    return result;
}
void baz()
{
    Foo field = bar(12);
}

Без оптимизаций это будет выглядеть на низком уровне примерно так:

struct Foo {int a;};
void __cdecl bar(Foo* __out, int a)
{
    Foo result;
    result.a = a;
    new(__out) Foo(result); // Вызов конструктора копирования
}
void __cdecl baz()
{
    Foo field;
    bar(&field, 12);
}

С copy elision bar станет таким:

void __cdecl bar(Foo* __out, int a)
{
    __out->a = a;
}
Answer 2

В качестве дополнения.

Можно вспомнить, что костылем для семантики перемещения до C++11 был auto_ptr, и сыграть с ним...

...но замечу, что Мейерс в "Эффективном и современном C++" рекомендовал не полагаться на перемещение при возврате из функции. Так что постарайтесь, чтобы не было нескольких путей возврата из функции, и возвращался один объект - этого должно быть достаточно для оптимизации.

И еще - на всякий случай:

Data foo() {
    Data data_old();   
    //...
    return data_old;
}

В первой строке у вас - объявление функции data_old. Надеюсь, это опечатка только в вопросе.

READ ALSO
цикл for i:=1 to 6 do из паскаля в C++ [требует правки]

цикл for i:=1 to 6 do из паскаля в C++ [требует правки]

Здравствуйте В паскале можно сделать:

389
Кроссплатформенная работа с USB

Кроссплатформенная работа с USB

Исходно есть Linux и Windows приложение основанные на Qt, задача заключается в том чтобы с помощью этих приложений в момент подключения USB накопителя...

350