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 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.