2014-12-16 17 views
6

C++ 11'de, geçici nesneleri önlemek için hareket semantikleri STL kapsayıcılarında uygulandığını biliyorum. Ve insanlar şimdi değere göre dönen fonksiyonları yazmak için mükemmel olduğunu söylüyorlar. Ancak, yeryüzünde kopyalamanın kaç kez gerçekten önlendiğine dair kafa karışıklığım var. Aşağıdaki örneğe bakın lütfen:STL konteynırları semantiği taşıyor ve değere göre dönüyor: Kopyalamanın kaç katı uzaklaşılıyor?

vector<int> myVector() { 
    vector<int> res; 
    res.push_back(4); 
    res.push_back(5); 
    return res; 
} 

vector<int> v = myVector(); 

Benim anlayış lar yapıcı vector<int>(const vector<int> &) çağrılır kopya vector<int> v = myVector();vector<int>' değerlendirirken C++ 03, myVector, res bir kopyasını (4 kez kopyalanmış 5) döndürür olmasıdır (4 , 5 iki kez kopyalandı. Ancak hareket semantiği ile C++ 11'de, 4 ve 5'un hangi kopyasından kaçınıldığını bilmek istiyorum? her ikisi de? Dönüş değeri optimizasyonu da, bir kez 4 ve 5 kopyalarını azaltmak için çağrılır mı?

+2

C++ 03'te, her ikisi de elemenasyona tabi iki kopyadır. C++ 11'de, her ikisi de seçime tabi iki hamle. –

+0

Neden iki hareket var? – Allanqunzi

+0

Aynı nedenden dolayı C++ 03'te iki kopya olabilir - "res" den dönüş değerine bir hareket ve daha sonra "v" ye bir hareket. –

cevap

4

C++ 03'te iki kopya ve C++ 11'de iki hareket vardır.

Her iki C++ 03 ve C++ 11'de de kopya/hamle seçime tabi tutulur ve bu şekilde (bunun gibi bir örnekte) hiçbir kopya/taşıma gerçekleşmez.

vector<int> myVector() { 
    vector<int> res; 
    res.push_back(4); 
    res.push_back(5); 
    return res;// <- Here we construct the return value with res 
} 

// here we construct v with the return value of myVector: 
vector<int> v = myVector(); 

myVector dönüş değeri içine res üzerinden elision biraz kırılgandır. C++ 11'de, elemenasyon başarısız olursa oluşabilecek move'da (hiçbir şey yapmadan) neredeyse 3 kat kopyalanır ve 3 işaretçi silinir. C++ 03'te, seçim başarısız olursa oluşabilecek kopyalar pahalı olabilir (bellek ayırma ve O (n) kopyaları).

Elision, işlem dönüştürücülerinin, davranıştaki bir değişikliğe neden olsa bile (yani, as-if sınaması başarısız olur) iki değerin bire dönüştürüldüğü belirli durumlarda yapabileceği işlem derleyicisinin adıdır.

Bu olduğunda, birleşik değerin iki yaşam süresinin bir ömrü vardır. Yukarıdaki durumda, res yerel değişkeni ve myVector() dönüş değeri, NRVO kuralı (dönüş değeri optimizasyonu olarak adlandırılır) tarafından seçilebilir. Üste Geri Bildirim Ver Daha fazla bilgi Daha fazla bilgi için bkz: http://support.microsoft.com/contactus/index.aspx. myVector dönüş değeri, A a = b formunun bir ifadesi olduğu için v şeklinde seçilebilir; burada b anonim bir değerle sonuçlanan bir ifadedir (bu tür anonim değerlerin adı C++ 03'ten C++ 11'e değişmiştir) Kullanmayacağım), özellikle myVector()'un dönüş değeri.

Bu, resv kullanım ömrüne ve myVector()'un geri dönüş değerinin tek bir değerin ömründe birleştirilmesine neden olur. Pratikte, myVector()'un geri dönüş değerinin (çağrı düzenine göre) gideceği ve v olduğu ve v kapsamının v kapsam dışına çıkacağı noktaya kadar res doğrudan doğruya yerleştirildiği durumda ne olur? return ifadesi ve v = myVector() adresinde bulunmaktadır.

Veya diğer bir deyişle, v doğrudan myVector içinde yapılandırılmıştır.

+0

Böylece v yıkılana kadar hiçbir yıkıcı aramayacak mı? – Allanqunzi

+1

@ user2345484 belki de. Elision'a standart tarafından izin verilir, garanti edilmez. (Pratikte, ne zaman olacağını tahmin edebilirsiniz). Her iki eleme vakası ortaya çıkarsa, evet, bir ömür boyu yalnızca bir değer vardır ve 'v' kapsam dışına çıkana kadar yok olmaz. Şimdi, 'v' ANALİZ değişkene seçilebilirdi, bu durumda yıkım daha sonra olurdu. – Yakk