Есть ли случаи, когда идеальная пересылка действительно повышает производительность? - PullRequest
1 голос
/ 03 мая 2020

Я не совсем уверен, правильно ли я понимаю совершенную пересылку. Я протестировал две функции:

template <typename T,typename Arg>
T createA(Arg&& a){
  return T(std::forward<Arg>(a));
}


template <typename T,typename Arg>
T createB(Arg a){
  return T(std::move(a));
}

и сравнил скомпилированный код . Похоже, что нет никакой разницы с оптимизацией. Есть ли на самом деле выигрыш в производительности с использованием идеальной пересылки на практике по сравнению с обычным проходом по значению, за которым следует движение? Я использую это неправильно?

Редактировать : Изменен код для использования шаблонных функций

1 Ответ

1 голос
/ 03 мая 2020

В основном у вас есть эти параметры конструктора:

class myclass {
public:
    // #1 myclass(const std::string& s) : s(s) {}
    // #2 myclass(std::string&& s) : s(std::move(s)) {}

    // #3 myclass(std::string s) : s(std::move(s)) {}

    // #4 template <typename T> myclass(T&& t) : s(std::forward<T>(t)) {}

    std::string s;
};

#3 не может присутствовать с #1 или #2 -> неоднозначным вызовом

и вызовом

std::string s;
myclass A(s);
myclass B(std::move(s));
myclass C("temporary");
myclass D({5, '*'});

Ниже приведено количество конструкторов копирования / перемещения

                        | A | B | C | D |
------------------------|---|---|---|---|
1                  Copy | 1 | 1 | 1 | 1 |
const l-value ref  Move | 0 | 1 | 0 | 0 |
                  Other | 0 | 0 | 1 | 1 |
------------------------|---|-v-|-v-|-v-|
2                  Copy | X | 0 | 0 | 0 |
r-value ref        Move | X | 1 | 1 | 1 |
                  Other | X | 0 | 1 | 1 |
------------------------|---|---|---|---|
3                  Copy | 1 | 0 | 0 | 0 |
by value           Move | 1 | 2 | 1 | 1 |
                  Other | 0 | 0 | 1 | 1 |
------------------------|---|---|---|---|
4                  Copy | 1 | 0 | 0 | X |
Forwarding ref     Move | 0 | 1 | 0 | X |
                  Other | 0 | 0 | 1 | X |
----------------------------------------/

Возможные конфигурации:

  • #1 только: обрабатывать все случаи, но копировать для временных
  • #1/#2: (B / C / D будет использовать #2), поэтому лучшие результаты, за исключением конструкции на месте
  • #3 только: обрабатывать все случаи, но делает дополнительное перемещение
  • #4 только: обработка большинства обычных случаев, лучшие результаты
  • #1/#2/#4: лучшие результаты (обратите внимание, что #4) имеет точное совпадение с неконстантным l-значением)
  • #2/#4: лучшие результаты

Цель #3 - записать только одну перегрузку.

Как видно, ссылка на пересылку (#4) имеет лучший результат.

...