Сообщение Re: Правильно ли я понимаю перемещение от 19.05.2016 19:59
Изменено 19.05.2016 21:05 Erop
Здравствуйте, dosik, Вы писали:
D>Таким образом мы избавляемся от одного конструктора и одного деструктора? Или же конструкторы и деструкторы будут вызваны оба раза, а при перемещении произойдет лишь "передача" внутренностей?
По стандарту 98 поведение должно быть таким:
и с 98 было в стандарте же можно делать ВНУТРИ ФУНКЦИИ RVO, а с 03 и NRVO
В данном случае NRVO будет означать следующее:
RVO же, означает следующее:
Для этого исходную some_func надо писать так:
И для такой редакции в С++11 будет доступна move-семантика. То есть эквивалентный код будет такой:
Правда, насколько я понимаю, RVO всё равно доступна компилятору, так как у std::vector есть доступный конструктор копии.
Чтобы move-семантика была доступна в оригинальной версии, надо писать так:
Но я не понимаю зачем, если у возвращаемого типа есть доступный конструктор копии.
Другое дело, если мы, например, std::unique_ptr захотим вернуть...
При этом в любом случае ВЫЗЫВАБЩИЙ код от того, что ВНУТРИ функции пишут зависеть не должен, если не включена оптимизация вызывающего кода, использующая доступ к определению тела функции в точке вызова (то, что обычно понимают под inline)
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::vector<some_type> some_func(void* resultBuffer, ...) {
std::vector<some_type> result;
......
//Some code to fill vector
......
return std::move( result );
}Но я не понимаю зачем, если у возвращаемого типа есть доступный конструктор копии.
Другое дело, если мы, например, std::unique_ptr захотим вернуть...
При этом в любом случае ВЫЗЫВАБЩИЙ код от того, что ВНУТРИ функции пишут зависеть не должен, если не включена оптимизация вызывающего кода, использующая доступ к определению тела функции в точке вызова (то, что обычно понимают под inline)
Re: Правильно ли я понимаю перемещение
Здравствуйте, dosik, Вы писали:
D>Таким образом мы избавляемся от одного конструктора и одного деструктора? Или же конструкторы и деструкторы будут вызваны оба раза, а при перемещении произойдет лишь "передача" внутренностей?
По стандарту 98 поведение должно быть таким:
и с 98 было в стандарте же можно делать ВНУТРИ ФУНКЦИИ RVO, а с 03 и NRVO
В данном случае NRVO будет означать следующее:
RVO же, означает следующее:
Для этого исходную some_func надо писать так:
И для такой редакции в С++11 будет доступна move-семантика. То есть эквивалентный код будет такой:
Правда, насколько я понимаю, RVO всё равно доступна компилятору, так как у std::vector есть доступный конструктор копии.
Но я не понимаю зачем тут move-семантика, если у возвращаемого типа есть доступный конструктор копии.
Другое дело, если мы, например, std::unique_ptr захотим вернуть...
При этом в любом случае ВЫЗЫВАЮЩИЙ код от того, что ВНУТРИ функции пишут зависеть не должен, если не включена оптимизация вызывающего кода, использующая доступ к определению тела функции в точке вызова (то, что обычно понимают под inline)
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)