Връщане на rvalue - какво не е наред с този код?

Попаднах на следния кодов фрагмент

std::string&& test()
{
    std::string m="Hello";
    return (std::move(m));
}

int main()
{
     std::string&& m = test();
}

Разбирам, че горният код е неправилен и опасен, но не знам защо. Засега това е моето разбиране за кода. Във функцията test

  1. в стека се създава локална std::string променлива, наречена m.

  2. След това този низ се връща, но вместо да се прави копие, съдържанието му се премества във временния. В този момент функцията test завършва с извикване на деструктора на променлива m (чието съдържание е преместено във временния)

  3. Временният вече е обвързан с препратката към rvalue m. И от това, което разбирам е, че временното ще остане живо, докато обвързващият му обект е жив и в обхват.

Може ли някой да ми каже къде може да греша? Защо кодът по-горе не е безопасен?


person James Franco    schedule 10.08.2015    source източник


Отговори (1)


Препратката към rvalue все още е препратка, вашият код е неправилен поради същата причина като функцията, показана по-долу

std::string& test()
{
    std::string m="Hello";
    return m;
}

И в двата случая функцията връща препратка към локална променлива. std::move не прави нищо друго освен прехвърляне m към string&&, така че няма temporary създаден, към който m в main след това се свързва. Когато test излезе, локалната променлива се унищожава и m е висяща препратка.

За да коригирате кода си, променете типа на връщане от string&& на string.

std::string test()
{
    std::string m="Hello";
    return m;   // std::move is redundant, string will be moved automatically
}

int main()
{
     std::string&& m = test();
}

Сега m в main може да се свързва с върнатата стойност на test и животът на това е удължен, за да съответства на този на m .

person Praetorian    schedule 10.08.2015