R-значение в C ++ 0x - PullRequest
       29

R-значение в C ++ 0x

3 голосов
/ 13 июня 2010

R-значения ИМХО являются большим улучшением в C ++, но в начале они кажутся довольно запутанными. Пожалуйста, посмотрите на код ниже:

#include <string>

std::string && foo (void)
{
    std::string message ("Hello!");

    return std::move (message);
}

void bar (const std::string &message2)
{
    if (message2 == "Bye Bye!")
        return;
}

int main ()
{
    bar (foo ());
}

Ссылка message2 - последний владелец исходного message объекта, возвращенного foo(), верно?

Ответы [ 2 ]

9 голосов
/ 14 июня 2010

Нет, это не правильно. Вы попали в обычную ловушку, которую делаете один, когда обнаружили ссылку на значение, как и Мотти в принятом ответе! (И я тоже сделал эту ошибку, в моем предыдущем тесте с rref)

Если вы не хотите стрелять себе в ногу при работе с rref, усвойте это:

В большинстве случаев функция, возвращающая ссылку на значение, так же глупа, как и функция, возвращающая нормальную ссылку.

Потому что ссылки на rvalue являются ... ссылками! Поэтому, если вы вернете ссылку - rvalue или нет - на message, вы вернете ссылку на объект, который был просто уничтожен, потому что он вышел из области видимости, поэтому вы возвращаете висячую ссылку. Это ошибка.

Кроме того, не пишите return std::move(message), потому что компилятор уже знает, что message - это временное значение (значение), поэтому нет необходимости изменять его с помощью std :: move. И на самом деле, написание return std::move(something) может предотвратить оптимизацию (по крайней мере на MSVC10, кажется, отключить RVO).

Итак, правильный и самый эффективный способ:

#include <string>
std::string foo (void)
{
    std::string message ("Hello!");
    return message;
}

void bar (const std::string& message2)
{
    if (message2 == "Bye Bye!")
        return;
}

int main ()
{
    bar (foo());
}

Старый добрый C ++ 03:)
Потому что NRVO начинает действовать, и нет ни копии, ни движения, только одна конструкция.

1 голос
/ 14 июня 2010

Редактировать: Возвращение ссылки на r-значение - это не то, что вы хотите сделать.Этот ответ был изначально написан, когда я все еще разбирался со ссылками r-значения в C ++ 11s.


Вы правы, message2 будет построен с использованием конструктора перемещения, так что он может уничтожитьпамять, выделенная message в foo, однако, это может не произойти, если используется оптимизация малой строки , тогда конструктор перемещения для короткой строки не будет более эффективным, чем конструктор копирования.

Еще одна вещь, на которую следует обратить внимание, это то, что вам не нужно явно использовать std::move при возврате значения, известно, что возвращаемые значения являются ссылками r-значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...