SORU
30 Mart 2011, ÇARŞAMBA


&& (Çift) işareti C 11 T anlamı nedir?

C 11 ve gözlemlediğim bir değişken bildirmek çift ve işareti, T&& var gibi bazı yeni özellikler araştırıyordum.

Bir başlangıç için, bu canavarın adı nedir? Google bize böyle noktalama işaretleri aramak için izin istiyorum.

Tam olarak ne yapardemek?

İlk bakışta, bir çift referans gibi görünüyor (C-tarzı çift işaretçiler T** var gibi), ama zor bir zaman bunun için bir dava düşünerek geçiriyorum.

CEVAP
30 Mart 2011, ÇARŞAMBA


rvalue reference (standartlar teklif doc) ilan eder.

Bu rvalue başvurular için bir tanıtım: http://www.artima.com/cppsource/rvalue.html.
Muhteşem derinlemesine Microsoft'un standart kütüphane geliştiricilerinden biri tarafından rvalue başvuruları bak burada: http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx.

C 03 başvurusu arasındaki en büyük fark (şimdi C 0x içinde lvalue başvuru denir) Sabit olmak zorunda kalmadan gibi geçici bir rvalue bağlamak. Böylece, bu sözdizimi artık yasal

T&& r = T();

rvalue başvurular öncelikle aşağıdakileri sağlar:

Taşıma semantiği. Yapıcı ve hareket atama operatörü şimdi inş-lvalue her zamanki başvurusu yerine bir rvalue başvuru alıyor tanımlanabilir. Hareket fonksiyonları kaynak değişmeden tutmak zorunda değildir dışında bir kopyası gibi; aslında, genellikle kaynak artık taşındı kaynaklara sahip olduğu gibi değiştirir. Bu gereksiz kopyalarını ortadan kaldırmak için harika, özellikle standart kütüphane uygulamalarında.

Örneğin, bir kopya yapıcı bu gibi görünebilir:

foo(foo const& other)
{
    this->length = other.length;
    this->ptr = new int[other.length];
    copy(other.ptr, other.ptr   other.length, this->ptr);
}

Eğer bu yapıcı bir geçici geçirildi, kopya sadece geçici olarak yok olacak biliyoruz çünkü gereksiz olurdu; neden bu kaynaklar geçici çoktan ayrılmış kullanmak değil mi? C 03, geçici geçti olduğumuzu tespit edemeyiz gibi kopyayı önlemek için yolu vardır. C 0x, aşırı bir hareket yapıcı olabiliriz:

foo(foo&& other)
{
   this->length = other.length;
   this->ptr = other.ptr;
   other.length = 0;
   other.ptr = nullptr;
}

Büyük fark dikkat: yapıcı aslında bağımsız hareket değiştirir. Bu etkili bir "nesne inşa edilmekte olan geçici, böylece gereksiz kopya ortadan kaldırır." hareket olurdu

Taşı yapıcısı açıkça rvalue başvuruları std::move işlevi (sadece dönüşüm gerçekleştirir) kullanarak dönüştürülen olmayan sabit lvalue başvurular için geçici ve kullanılacaktır. Aşağıdaki kodu hem çağırmak taşı f1 f2 kurucu:

foo f1((foo())); // Move a temporary into f1; temporary becomes "empty"
foo f2 = std::move(f1); // Move f1 into f2; f1 is now "empty"

Mükemmel iletme. rvalue başvurular bize doğru şablonu esas alan bir işlev için bağımsız iletmek için izin verir. Örneğin bu fabrika fonksiyon:

template <typename T, typename A1>
std::unique_ptr<T> factory(A1& a1)
{
    return std::unique_ptr<T>(new T(a1));
}

Eğer aradık factory<foo>;(5), bağımsız olacak sonucuna int&, olmaz bağlamak için bir literal 5, bile foo'nin kurucu alır int. İyi, A1 const& ama foo yapıcı argüman alırsa olmayan sabit başvuru olarak ne kullanabiliriz? Gerçekten genel bir fabrika işlevi yapmak, A1 const& A1& aşırı yük fabrika ve olurdu. Eğer fabrika 1 parametre türü alırsa iyi olabilir, ama her ek parametre türü gerekli aşırı yük set 2 ile çarpın. Çok hızlı bir şekilde unmaintainable.

rvalue başvurular standart kitaplığı düzgün ileri/rvalue başvurular lvalue olabilir std::forward bir işlev tanımlamak için izin vererek bu sorunu çözmek. std::forward nasıl çalıştığı hakkında daha fazla bilgi için this excellent answer bkz.

Bu bize böyle bir fabrika işlevi tanımlamanıza olanak sağlar:

template <typename T, typename A1>
std::unique_ptr<T> factory(A1&& a1)
{
    return std::unique_ptr<T>(new T(std::forward<A1>(a1)));
}

Şimdi argüman bu rvalue/lvalue-ness geçmiş zaman korunur T'in kurucu. Eğer fabrika bir rvalue, T'In kurucu bir rvalue ile denir. denir demektir Eğer fabrika bir lvalue, T'In kurucu bir lvalue olarak adlandırılır. olarak adlandırılır Geliştirilmiş fabrika işlevi bir özel kural nedeniyle çalışır:

İşlev parametre türü. formu T bir şablon olduğu T&& parametre ve fonksiyon argümanı tür bir lvalue 33* *yazın A&. şablon değişkeni kesintisi için kullanılır.

Böylece, fabrika gibi kullanabilirsiniz:

auto p1 = factory<foo>(foo()); // calls foo(foo&&)
auto p2 = factory<foo>(*p1);   // calls foo(foo const&)

Önemli rvalue başvuru özellikleri:

  • Aşırı çözümleme içinlvalues lvalue referanslar için bağlayıcı tercih ve rvalues rvalue başvurular için bağlayıcı bir tercih. Geçici bir kopya kurucu / atama operatörü / hareket atama operatörü yapıcı bir hareket yürütmesini tercih ederim bu yüzden.
  • rvalue başvurular örtülü bir dönüştürme sonucu dişler için rvalues ve örtülü olarak bağlanacaktır. yani float f = 0f; int&& i = f; yüzer int örtük olarak dönüştürülebilir çünkü iyi biçimlendirilmiş; başvuru dönüşüm sonucu, bir geçici olacaktır.
  • Rvalue başvurular adlandırılır lvalues. İsimsiz rvalue başvurular rvalues.Bu önemli std::move çağrı neden gerekli olduğunu anlamak için: foo&& r = foo(); foo f = std::move(r);

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Andrey Menshikov

    Andrey Mensh

    28 Ocak 2012
  • Call Me Howard

    Call Me Howa

    18 AĞUSTOS 2012
  • Sean Murphy

    Sean Murphy

    4 ŞUBAT 2009