Doğru yanıt, söz konusu C++ standardına bağlıdır.
C++ 11 hakkında konuşuyorsak, clang doğrudur (açık bir harekete ihtiyaç vardır). C++ 14 hakkında konuşuyorsak, gcc doğrudur (açık bir harekete gerek yoktur).
C++ 11 N3290/[class.copy]/P32 diyor:
When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. If overload resolution fails, ...
Bu dönüş ifadesi işlev dönüş türü ile aynı türe sahip olduğunda sadece örtülü hareketlen ister.
Ancak, CWG 157910 bunu değiştirdi ve bu hata raporu C++ 11'den sonra ve C++ 14 için de kabul edildi. Bu, aynı paragraf şimdi okur:
When the criteria for elision of a copy/move operation are met, but not for an exception-declaration, and the object to be copied is designated by an lvalue, or when the expression in a return
statement is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. If the first overload resolution fails or was not performed, ...
Bu modifikasyon temelde dönüş ifadesi tipi olmasını sağlar konvertibl-işlev dönüş türü ve hala örtülü hareket için uygun olması.
Bu, kodun __cplusplus
değerine bağlı olarak #if
/#else
gereksinimine sahip olduğu anlamına mı geliyor?
Bunu yapabilir, ama rahatsız etmem.Ben C++ 14 hedef olsaydı, ben sadece olurdu: Kod beklenmedik bir C++ 11 derleyici altında çalıştırılır
return i;
varsa, hata derleme sırasında haberdar ve bu önemsiz olacak düzeltmek için:
return std::move(i);
sadece C++ 11 hedefliyorsanız, move
kullanın.
Hem C++ 11 hem de C++ 14 (ve ötesini) hedeflemek isterseniz, move
'u kullanın. move
'u kullanmanın olumsuz tarafı, RVO'yu (Dönüş Değeri Optimizasyonu) engelleyebileceğinizdir. Ancak, bu durumda, RVO bile yasal değildir (return
ifadesinden işlevin dönüş türüne dönüşümü nedeniyle). Ve bu nedenle, bedava move
hiçbir şeye zarar vermez. o olmadan şeyler hala C++ 11 yılında derlemek ve pahalı bir kopya dönüşüm çağırmak durumunda hareket aksine
C++ 14 hedefleme bile bir karşılıksız move
meyledeceğini olabilecek bir zamandır, dönüşümü. Bu durumda, yanlışlıkla C++ 11 altında derleme sessiz bir performans hatası oluşturur. Ve C++ 14 altında derlendiğinde, karşılıksız move
'un hala zararlı etkileri yoktur.
Bunun için neye ihtiyacınız olduğunu anladığımızda daha iyi cevaplar verebileceğimizden şüpheleniyorum. Şu anda, bu make_unique yerine make_shared çağrılarak önemsiz bir şekilde çözülebilir. Bunun mümkün olmadığının bir sebebi var ve bu sebebi anlamaya yardımcı olur. – Elliott
@Elliott: Ne çözülebilir? Bir şeyi nasıl çözeceğini sormuyor, sahip olduğu kodun standartlara uygun olup olmadığını soruyor. –