Re: Правильно ли я понимаю перемещение
От: Erop Россия  
Дата: 19.05.16 19:59
Оценка:
Здравствуйте, dosik, Вы писали:


D>Таким образом мы избавляемся от одного конструктора и одного деструктора? Или же конструкторы и деструкторы будут вызваны оба раза, а при перемещении произойдет лишь "передача" внутренностей?


По стандарту 98 поведение должно быть таким:

std::vector<some_type>& some_func(void* resultBuffer, ...) {
    std::vector<some_type> result;
    ......
    //Some code to fill vector
    ......
    return *::new(resultBffer) std::vector<some_type>( result );
}
....

// выделили место под std::vector<some_type> need;
std::vector<some_type>&need = some_func(место_под_need, ...);
// с этого момента вызывающая сторона отвечает за разрушение need


и с 98 было в стандарте же можно делать ВНУТРИ ФУНКЦИИ RVO, а с 03 и NRVO
В данном случае NRVO будет означать следующее:
std::vector<some_type>& some_func(void* resultBuffer, ...) {
    std::vector<some_type>& result = *new(resultBffer) std::vector<some_type>;
    // с этого момента и до return some_func отвечает за разрушение result 
    ......
    //Some code to fill vector
    ......
    return result;  // с этого момента за разрушение result отвечает вызывающая сторона
}


RVO же, означает следующее:
std::vector<some_type>& some_func(void* resultBuffer, ...) {
    
    //тут код, который вычисляет параметры конструктора std::vector<some_type>
    ......
    return *::new(resultBffer) std::vector<some_type>( те самые параметры конструктора );
}


Для этого исходную some_func надо писать так:
std::vector<some_type> some_func(...) {
    
    //тут код, который вычисляет параметры конструктора std::vector<some_type>
    ......
    return std::vector<some_type>( те самые параметры конструктора );
}

И для такой редакции в С++11 будет доступна move-семантика. То есть эквивалентный код будет такой:
std::vector<some_type>& some_func(void* resultBuffer, ...) {
    
    //тут код, который вычисляет параметры конструктора std::vector<some_type>
    ......
    std::vector<some_type> __temporary_object__( те самые параметры конструктора );
    return *new(resultBffer) std::vector<some_type>( static_cast<std::vector<some_type>&&>( __temporary_object__ ) );
}

Правда, насколько я понимаю, RVO всё равно доступна компилятору, так как у std::vector есть доступный конструктор копии.
Но я не понимаю зачем тут move-семантика, если у возвращаемого типа есть доступный конструктор копии.
Другое дело, если мы, например, std::unique_ptr захотим вернуть...

При этом в любом случае ВЫЗЫВАЮЩИЙ код от того, что ВНУТРИ функции пишут зависеть не должен, если не включена оптимизация вызывающего кода, использующая доступ к определению тела функции в точке вызова (то, что обычно понимают под inline)
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Отредактировано 19.05.2016 21:05 Erop . Предыдущая версия . Еще …
Отредактировано 19.05.2016 20:05 Erop . Предыдущая версия .
Re[2]: Правильно ли я понимаю перемещение
От: uzhas Ниоткуда  
Дата: 19.05.16 20:55
Оценка: 10 (1)
Здравствуйте, Erop, Вы писали:

E>Чтобы move-семантика была доступна в оригинальной версии, надо писать так:


достаточно писать

return result;

Re[3]: Правильно ли я понимаю перемещение
От: Erop Россия  
Дата: 19.05.16 21:06
Оценка:
Здравствуйте, uzhas, Вы писали:

U>достаточно писать

U>

U>return result;


Да, точно, это я тупанул.
Спасибо.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: Правильно ли я понимаю перемещение
От: antropolog  
Дата: 19.05.16 22:35
Оценка:
Здравствуйте, uzhas, Вы писали:

U>здесь уничтожено три объекта типа A

U>всю ответственность за потери беру на себя
U>это поведение вполне соответствует стандарту

вполне соответствует стандарту (12.8/31) и отсутствие промежуточной переменной, и данное (дефолтное) поведение вы беспардонно отключили ключом компиляции (-fno-elide-constructors). ТС тянется к знаниям, а вы его только сбиваете. Нехорошо.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.