Genellikle/her zaman std kullanabilir miyim::std yerine ileri gitmek mi?
Scott Meyers'in ve Ötesi 2012 C Konferansı talk on Universal References, ve şu ana kadar her şey mantıklı. izliyorum Ancak, bir seyircinin de merak ediyordum o da yaklaşık 50 dakikalık bir soru sorar. Meyers olmayan deyimsel çünkü cevap umurunda olmadığını söylüyor ve onun aptal bir sakıncası var, ama yine de ilgileniyorum.
Kod sunulan aşağıdaki gibidir:
// Typical function bodies with overloading:
void doWork(const Widget& param) // copy
{
// ops and exprs using param
}
void doWork(Widget&& param) // move
{
// ops and exprs using std::move(param)
}
// Typical function implementations with universal reference:
template <typename T>
void doWork(T&& param) // forward => copy and move
{
// ops and exprs using std::forward<T>(param)
}
Nokta rvalue başvurusu attığımızda, bir rvalue biz biliyoruz, std::move
bir rvalue aslında korumamız gerekiyor. Ne zaman biz bir evrensel referans (T&&
nereye T
çıkarılabilir tip), istiyoruz std::forward
korumak aslında bu olabilir bir lvalue veya bir rvalue.
Şimdi soru şu: beri std::forward
korur değeri olmadığını kabul işlevi ya da bir lvalue veya bir rvalue ve std::move
sadece atan bağımsız bir rvalue, sadece std::forward
her yerde? std::forward
std::move
, biz her durumda std::move
gibi davranır ya Meyers tarafından kaçırılmış olan davranış' genelleme? bazı önemli farklılıklar vardır
Herkes Meyers doğru söylediği gibi, olmayan deyimsel tamamen çünkü, Ama şu da std::move
geçerli bir kullanım: yapması gerektiğini düşündüren değilim
void doWork(Widget&& param) // move
{
// ops and exprs using std::forward<Widget>(param)
}
CEVAP
İkisi çok farklıtamamlayıcıaraçlar.
std::move
şüpheleribağımsız ve koşulsuz rvalue bir ifade oluşturur. Bu anlamda gerçek bir nesne veya değişken uygulamak için yapar.std::forward
zorunlu şablon bağımsız değişken (bu belirtmeniz gerekir!) alır ve sihirli bir şekilde lvalue başvuru veya rvalue bir ifade türü ne bağlı olarak (&&
ve çöken kuralları ekleme gereği) oluşturur. Bu sadece mantıklı bir çıkarım, şablonu esas alan bir işlev bağımsız değişkeni için uygulamak için yapar.
Belki aşağıdaki örnekler, bu biraz daha iyi göstermek:
#include <utility>
#include <memory>
#include <vector>
#include "foo.hpp"
std::vector<std::unique_ptr<Foo>> v;
template <typename T, typename ...Args>
std::unique_ptr<T> make_unique(Args &&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); // #1
}
int main()
{
{
std::unique_ptr<Foo> p(new Foo('a', true, Bar(1,2,3)));
v.push_back(std::move(p)); // #2
}
{
v.push_back(make_unique<Foo>('b', false, Bar(5,6,7))); // #3
}
{
Bar b(4,5,6);
char c = 'x';
v.push_back(make_unique<Foo>(c, b.ready(), b)); // #4
}
}
Mevcut durumda, bir beton var #2, p
, nesne ve koşulsuz olarak hareket etmek istiyoruz. Sadece std::move
mantıklı. Bir şey yok "" burada. ileri var Adında bir değişken var ve bunu taşımak istiyoruz.
Öte yandan, durum #1 argümanlar herhangi bir listesini kabul eder, ve her bir bağımsız değişken orijinal arayın aynı değer kategorisi olarak iletilmesi gerekiyor. Örneğin, #3 geçici değişkenleri ifadeler ve böylece rvalues olarak iletilecek. Ama aynı zamanda durum gibi nesneleri yapıcı çağrısında adlı karma yapabiliriz #4 ve lvalues olarak iletme ihtiyacımız var.
Ne zaman ileriye doğru bir beyan kulla...
Bash yerine Python kullanabilir miyim?...
Node.js JS yerine CoffeeScript kullana...
Ne desen unıx/linux kabuk eşleşen zama...
C# 4.0: varsayılan değeri isteğe bağlı...