Итак, мое понимание семантики перемещения заключается в том, что они позволяют вам переопределять функции для использования с временными значениями (rvalues) и избегать потенциально дорогостоящих копий (путем перемещения состояния из неназванного временного в ваше имя lvalue).Почему семантика перемещения необходима для исключения временных копий?
Мой вопрос: зачем нам нужна специальная семантика? Почему компилятор C++ 98 не смог удалить эти копии, поскольку компилятор определяет, является ли данное выражение lvalue или rvalue? В качестве примера:
void func(const std::string& s) {
// Do something with s
}
int main() {
func(std::string("abc") + std::string("def"));
}
Даже без C++ 11 Переходит семантику, компилятор все равно должен быть в состоянии определить, что выражение передается func()
является Rvalue, и, таким образом, копия временного объекта не требуется. Так почему же это различие? Похоже, что это применение семантики перемещения - это, по сути, вариант копирования или других подобных оптимизаций компилятора.
В качестве другого примера, зачем нужно иметь код, как показано ниже?
void func(const std::string& s) {
// Do something with lvalue string
}
void func(std::string&& s) {
// Do something with rvalue string
}
int main() {
std::string s("abc");
// Presumably calls func(const std::string&) overload
func(s);
// Presumably calls func(std::string&&) overload
func(std::string("abc") + std::string("def"));
}
Похоже, что перегрузка const std::string&
может обрабатывать оба случая: lvalues, как обычно, и rvalues как константная ссылка (поскольку временные выражения рода сопзЬ по определению). Поскольку компилятор знает, когда выражение является значением lvalue или rvalue, оно может решить, следует ли исключать копию в случае rvalue.
В принципе, почему семантика перемещения считается специальной, а не только оптимизацией компилятора, которая могла быть выполнена компиляторами pre-C++ 11?
Не могли бы вы объяснить, насколько это существенно отличается от моего второго примера выше? –
Представьте, что вы являетесь компилятором, генерирующим код для 'func' ... и могут быть вызовы к нему в других единицах перевода ... вы переходите из параметра или нет? –