Можете ли вы использовать make_unique непосредственно в вызове функции? - PullRequest
0 голосов
/ 07 мая 2019

Я пытаюсь обновить код, который передает новый объект. Цель состоит в том, чтобы управлять им с помощью умного указателя. Сложив, это выглядит так:

class X
{
    shared_ptr<Y> yptr;

    X() : yptr(Y::create(new Z())){}
};

class Y
{
    Z* zptr;
    static shared_ptr<Y> create(Z* zp)
    {
        if(!zp) return nullptr;
        else return shared_ptr<Y>(new Y(zp));
    }

    Y(Z* zp) : zptr(zp){}
}

Пока что это похоже на работу:

class X
{
    shared_ptr<Y> yptr;

    X() : yptr(Y::create(  std::move(  std::make_unique<Z>(Z())  )  )){}
};

class Y
{
    unique_ptr<Z> zptr;
    static shared_ptr<Y> create(unique_ptr<Z> zp)
    {
        if(!zp) return nullptr;
        else return shared_ptr<Y>(new Y(std::move(zp)));
    }

    Y(unique_ptr<Z> zp) : zptr(std::move(zp)){}
}

У меня вопрос: нужен ли первый std :: move () (вокруг make_unique)? Visual Studio, похоже, не возражает против этого. Я предпочел бы иметь точное понимание, прежде чем я начну вносить подобные изменения в других местах, где производительность более критична.

Ответы [ 3 ]

0 голосов
/ 07 мая 2019

Мой вопрос: нужен ли первый std :: move () (вокруг make_unique)?

, если вы имеете в виду эту строку:

X() : yptr(Y::create(  std::move(  std::make_unique<Z>(Z())  )  )){}

затемнет, это совершенно не нужно, так как std::make_unique<Z> возвращает временное значение, которое уже prvalue.Вы можете сделать что-то вроде этого:

auto ptr = std::move( std::move( std::move( std::make_unique<Z>() ) ) );

вместо

auto ptr = std::make_unique<Z>();

, но все это moves не нужно, и факт его компиляции ясно показывает, что.

0 голосов
/ 07 мая 2019

Да! Движение вокруг make_unique не нужно.

std::move существует для преобразования ссылки l-значения & (которая относится к существующему объекту) в ссылку r-значения && (которая представляет временное значение или что-то, из чего можно перемещаться).

Если вы присваиваете unique_ptr именованной переменной, тогда вам действительно нужно std::move из нее, если вы хотите передать ее право собственности (обычно; см. Ниже). Вы не можете напрямую связать ссылку на r-значение с переменной.

Значение, возвращаемое выражением или вызовом функции, такое как unique_ptr, возвращаемое make_shared, является временным, и поэтому оно может естественно связываться с выражением r-значения и неявно перемещаться из.

Обратите внимание, что в некоторых особых случаях вам не нужно использовать std::move:

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

    MyClass(std::string&& s) : m_mystring(s) {} copy -constructs m_mystring

    MyClass(std::string&& s) : m_mystring(std::move(s)) {} move-constructs m_mystring

    Как правило, переменные с именами не переносятся неявно.

  • Если вы возвращаете локальную переменную по значению из функции, этот объект может автоматически перемещаться из так называемой Оптимизация именованного возвращаемого значения . Это дает хороший прирост скорости возврата по значению. Вам не нужно много думать об этом на практике, просто имейте в виду, что return std::move(whatever); почти всегда неверен.

0 голосов
/ 07 мая 2019

Краткий ответ: Да

Вызов функции std::make_unique<Z>() возвращает значение r, поэтому нет необходимости переносить его в std::move(), если вы передаете его непосредственно в другую функцию.

...