2016-12-01 4 views
2

Является ли следующий случай std::move излишним?Является ли следующий случай std :: move излишним?

std::string member; 

obj(std::initializer_list<std::string> p_list) 
    : member {std::move(join(p_list))} 
{} 

Это функция присоединения:

std::string join(string_initializer_list p_list) { 
    size_t size {}; 
    for (auto const & s : p_list) { 
     size += s.size(); 
    } 
    std::string output; 
    output.reserve(size); 
    for (auto const & s : p_list) { 
     output.append(s); 
    } 
    return output; 
} 
+0

Что такое 'join'? – ildjarn

+0

Я отредактировал вопрос;) –

+0

В каких сценариях std :: move будет полезен? –

ответ

4

Нет, вам не нужно std::move. Функция std::move заключается в том, чтобы передать любое значение в значение r. Ваша функция уже возвращает значение rvalue, поэтому приведение не влияет на привязку результата к ссылке (это то, что вам нужно, чтобы инициализировать member из rvalue).

В самом деле, используя std::move активно ингибирует копию Пропуска, поэтому строгий pessimization:

std::string s = join({});    // construct from prvalue, elidable, 
             // elision mandatory in C++17 

std::string s = std::move(join({})); // temporary object must be constructed, 
             // s is initialized by moving from the 
             // temporary 

В первой форме, std::string s = join({});, копия элизия означает, что возвращаемый объект join строится непосредственно в место s (временные объекты не построены и не копируются или не перемещаются), и кроме того, переменная output в теле функции также устранена и построена непосредственно в возвращаемом значении, то есть в s. С std::move первый шаг элиции недоступен.

+0

Этот случай на самом деле потенциально разрушает RVO, не так ли? – erip

+0

@erip: Нет, это совсем другая ситуация: вот если вы сказали 'return std :: move (output)' в теле функции. Интересно, что аргумент кажется, похоже, противоположным: 'output' действительно является lvalue, но по причинам специальной магии он фактически рассматривается как rvalue в этой ситуации. –

+0

Ах, упс. :) Спасибо за ответ! Ценить это. – erip

3

Учитывая вашу join функции нормальна, и возвращает std::string, да, std::move было бы излишним; возвращение от join уже является r-значением.

Кроме того, без std::move, копировать элизия означает, что он может построить результат на месте без std::move, при использовании std::move может заставить это сделать временный string, вызовите конструктор перемещения для инициализации member, а затем уничтожить временный; не много работы (несколько копий указателя в основном), но больше, чем вам нужно.

+0

Я отредактировал вопрос, чтобы показать функцию соединения;) –

+0

@DagobertoPires: И я отредактировал ответ, чтобы удалить квалификацию моих высказываний. :-) – ShadowRanger

+0

В каких сценариях std :: move будет полезен? Мне это интересно. –

0

Для ясности: любая функция, возвращающая значение, и, следовательно, возвращает значение rvalue, не нуждается в std :: move для применения, и, как уже указывали другие, это отрицательно влияет на оптимизацию производительности.

например.

SomeClass fn() 
{ 
... 
} 

// Move not needed, detrimental, as the function result is already an rvalue 
SomeClass x = std::move(fn()); 

просто сделать это, как обычно перед C++ 11:

SomeClass x = fn(); 

Вообще использование зЬй :: ход (х), когда х имеет имя. т.е. он является идентификатором, он не полезен во временных, за исключением особых обстоятельств (например, для предотвращения копирования),

На боковой ноте: Также не пытайтесь использовать std :: move to заставляют «сильный исключающий исключение» (например, если вы хотите, чтобы структура полностью копировалась или оставалась одна (т. е. консистенция) перед потенциальными исключениями), поскольку std :: move может вызывать в зависимости от перемещенного типа, и политика исключения этого типа может изменитесь под вами. Вместо этого используйте функцию-оболочку со статическим утверждением, объединенным с noexcept, кроме этого во время компиляции. См. Is there facility for a strong guaranteed exchange in C++

 Смежные вопросы

  • Нет связанных вопросов^_^