Могут ли компиляторы автоматически использовать семантику перемещения, когда подвижный объект используется в последний раз?
В последнее время я изучаю ссылки rvalue и пришел к выводу, что повсеместно использовать пропускную стоимость везде, где будет завершена полная копия объекта (для полного обоснования см. например Как уменьшить избыточный код при добавлении перегрузок ссылок rvalue? и Хотите скорость? Передайте по значению!), поскольку компилятор может автоматически оптимизировать копировать в таких случаях, как f(std::move(a));
, где f
определяется как void f(A a);
.
Одним из негативных последствий пересылки по всему миру является то, что весь код становится заваленным std::move
даже в простых случаях, таких как:
void Object::value(A a)
{
value_ = std::move(a);
}
Очевидно, если бы я написал только следующее:
void Object::value(A a)
{
value_ = a;
}
для компилятора не должно быть трудно понять, что a
находится ближе к концу его жизни даже без подсказки и не наказывать меня дополнительной копией. Фактически, компилятор должен уметь распознавать это даже в сложных функциях.
Вопросы:
-
Разрешена ли эта оптимизация стандартом С++ 0x?
-
Используют ли компиляторы? Даже в сложных случаях, т.е. Функция состоит из более чем одной строки?
-
Насколько надежна эта оптимизация, то есть я могу ожидать, что компилятор будет использовать ее столько, сколько я ожидаю, что компилятор применит Оптимизацию возвращаемого значения?
Ответы
Ответ 1
Разрешена ли эта оптимизация стандартом С++ 0x?
Нет.
Используют ли компиляторы? Даже в сложные случаи, т.е. функция состоит из более чем одной строки?
Нет.
Насколько надежна эта оптимизация, то есть я могу ожидать, что компилятор использовать его столько, сколько я ожидаю компилятор для применения возвращаемого значения Оптимизация?
Вы должны украсить A(const A&)
и A(A&&)
операторы печати и запустить тестовые примеры, представляющие для вас интерес. Не забудьте проверить аргументы lvalue, если эти варианты использования являются частью вашего дизайна.
Правильные ответы будут зависеть от того, насколько дорогой экземпляр и перемещение A
, сколько аргументов Object::value
на самом деле и сколько повторений кода вы готовы мириться.
Наконец, будьте очень подозрительными любого руководства, содержащего слова "всегда" или "везде". Например. Я использую goto
каждый раз в то время. Но у других программистов есть слова типа "никогда", связанные с goto
. Но время от времени вы не можете бить goto
как по скорости, так и по ясности.
Будут времена, когда вы должны одобрить пару foo(const A&) foo(A&&)
над foo(A)
. И раз вы этого не сделаете. Ваши эксперименты с украшенными копиями и перемещением участников помогут вам.