Чи ефективніше повернення за посиланням rvalue?


Відповіді:


246
Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

Це повертає звисаючу посилання, як і у випадку з посиланням на значення lvalue. Після повернення функції тимчасовий об'єкт буде знищений. Ви повинні повернутись Beta_abза вартістю, як наведено нижче

Beta_ab
Beta::toAB() const {
    return Beta_ab(1, 1);
}

Тепер належним чином переміщення тимчасового Beta_abоб'єкта у повернене значення функції. Якщо компілятор зможе, він уникне цілком переміщення, використовуючи RVO (оптимізацію повернутого значення). Тепер ви можете зробити наступне

Beta_ab ab = others.toAB();

І він перемістить побудову тимчасового в abабо зробить RVO, щоб пропустити виконання ходу або скопіювати взагалі. Я рекомендую вам прочитати посилання 101 BoostCon09 Rvalue, де пояснюється це питання, і як (N) RVO трапляється взаємодіяти з цим.


Ваш випадок повернення рецензії на оцінку було б гарною ідеєю в інших випадках. Уявіть, у вас є getAB()функція, яку ви часто використовуєте тимчасово. Це не оптимально, щоб він повертав посилання const lvalue для тимчасових тем rvalue. Ви можете реалізувати це так

struct Beta {
  Beta_ab ab;
  Beta_ab const& getAB() const& { return ab; }
  Beta_ab && getAB() && { return move(ab); }
};

Зауважте, що moveв цьому випадку це необов’язково, оскільки abце не є ні локальним автоматичним, ні тимчасовим рейтингом. Тепер, ref- && kvalifier каже, що друга функція викликається у часових значень rvalue, роблячи наступний хід, а не копіювати

Beta_ab ab = Beta().getAB();

51
Я завжди припускав, що висяча проблема відліку відходить автоматично, коли тип повернення був посиланням на r-значення. Радий, що я це випрямив, перш ніж мене вкусив. Стік розгромних клопів смокчуть.
deft_code

31
:) Дійсно, посилання на rvalue - це "просто посилання" на зразок посилання на lvalue. вони нічого не копіюють і не зберігають.
Йоханнес Шауб - ліб

9
що const & класифікатор на члені функціонує більше, ніж простий const?
Галінетта

4
+ 1-е, але розірване посилання: BoostCon09 Rvalue References 101
Siu Ching Pong -Asuka Kenji-

3
@galinette Це кваліфікаційні класи .
Малькольм

2

Це може бути більш ефективно, наприклад, у дещо іншому контексті:

template <typename T>
T&& min_(T&& a, T &&b) {
    return std::move(a < b? a: b);
}

int main() {
   const std::string s = min_(std::string("A"), std::string("B"));
   fprintf(stderr, "min: %s\n", s.c_str());
   return 0;
}

Як цікаве спостереження, на моїй машині clang++ -O3генерується 54 інструкції для коду вище та 62 інструкції для звичайного std::min. Однак, -O0він створює 518 інструкцій для коду вище, а 481 для регулярного std::min.


Мене бентежить ваша відповідь. Я спробував подібну (можливо) версію, але не вдався: ideone.com/4GyUbZ Чи можете ви пояснити, чому?
Декін

Ви використовували посилання на тимчасовий об'єкт for(:)і інтегрували його над розміщеним об'єктом. Виправити: ideone.com/tQVOal
wonder.mice

3
чи ця відповідь насправді неправильна? для шаблону параметр T, T && - це не посилання на значення r, а скоріше універсальне посилання, і для цього випадку ми завжди повинні викликати std :: вперед <T>, а не std :: move! Не кажучи вже про те, що ця відповідь прямо суперечить вищезгаданому.
xdavidliu

@xdavidliu ця відповідь є надуманим прикладом того, як повернення rvalue може бути більш ефективним. std::move()просто використовується як явний акторський склад, щоб більш чітко проілюструвати точку. Це не код, який ви б скопіювали та вставили у свій проект. Це не суперечить голосовій відповіді, оскільки там всередині функції створюється тимчасовий об'єкт. Тут повернутий об’єкт є одним із аргументів (тимчасові об’єкти знищуються як останній крок в оцінці повного виразу, який (лексично) містить точку, де вони були створені).
wonder.mice

2
@ wonder.mice, тоді замініть T на std :: string; тут взагалі не потрібно використовувати шаблони, а використання T&& як посилання на значення r - це просто жахливий стиль, який зайво заплутує людей, що не входять до шаблонів і r-значень.
xdavidliu
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.