C ++ 11 derleyicisini yeniden derlemenin, C ++ 11'in uygulama kalitesi ile neredeyse ilgisiz olan sınırsız performans artışlarına neden olabileceği 5 genel kategorinin farkındayım. Bunlar hareket semantiğinin çeşitleridir.
std::vector yeniden tahsis
struct bar{
std::vector<int> data;
};
std::vector<bar> foo(1);
foo.back().data.push_back(3);
foo.reserve(10); // two allocations and a delete occur in C++03
Her seferinde foo'ın tampon 03 C ++ yeniden tahsis edilmektedir her kopyalanan vectoriçinde bar.
C ++ 11'de bunun yerine bar::datatemelde ücretsiz olan s'yi taşır .
Bu durumda, bu stdkonteyner içindeki optimizasyonlara dayanır vector. Aşağıdaki her durumda, stdkapsayıcıların kullanımı, movederleyicinizi yükselttiğinizde C ++ 11'de "otomatik olarak" etkin semantiğe sahip C ++ nesneleri oldukları içindir . Bir stdkap içeren onu engellemeyen nesneler de otomatik geliştirilmiş moveyapıcıları devralır .
NRVO hatası
NRVO (adlandırılmış dönüş değeri optimizasyonu) başarısız olduğunda, C ++ 03'te kopyaya geri döner, C ++ 11'de tekrar harekete geçer. NRVO'nun arızaları kolaydır:
std::vector<int> foo(int count){
std::vector<int> v; // oops
if (count<=0) return std::vector<int>();
v.reserve(count);
for(int i=0;i<count;++i)
v.push_back(i);
return v;
}
ya da:
std::vector<int> foo(bool which) {
std::vector<int> a, b;
// do work, filling a and b, using the other for calculations
if (which)
return a;
else
return b;
}
Üç değerimiz var - dönüş değeri ve işlev içinde iki farklı değer. Elision, fonksiyon içindeki değerlerin dönüş değeriyle 'birleştirilmesine' izin verir, ancak birbiriyle birleştirilmesine izin verir. Her ikisi de birbirleriyle birleşmeden dönüş değeri ile birleştirilemez.
Temel sorun, NRVO elüsyonunun kırılgan olması ve returnsitenin yakınında olmayan değişikliklere sahip kodun , herhangi bir tanı yayılmadan aniden büyük performans düşüşlerine sahip olabilmesidir. Çoğu NRVO başarısızlık durumunda C ++ 11 a ile move, C ++ 03 ise bir kopya ile sonlanır.
İşlev bağımsız değişkenini döndürme
Burada seçim yapmak da imkansız:
std::set<int> func(std::set<int> in){
return in;
}
C ++ 11 bu ucuz: C ++ 03 kopyasını önlemek için hiçbir yolu yoktur. Parametrelerin ve dönüş değerinin ömrü ve konumu, arama kodu tarafından yönetildiği için işlevlere ilişkin bağımsız değişkenler döndürülemez.
Ancak, C ++ 11 birinden diğerine geçebilir. (Daha az oyuncak örneğinde, için bir şey yapılabilir set).
push_back veya insert
Son olarak kaplara eleme gerçekleşmez: ancak C ++ 11, kopyaları kaydeden rvalue move insert operatörlerini aşırı yükler.
struct whatever {
std::string data;
int count;
whatever( std::string d, int c ):data(d), count(c) {}
};
std::vector<whatever> v;
v.push_back( whatever("some long string goes here", 3) );
C ++ 03'te bir geçici whateveroluşturulur, daha sonra vektöre kopyalanır v. std::stringHer biri aynı veriye sahip 2 tampon ayrılır ve biri atılır.
C ++ 11'de geçici whateveroluşturulur. whatever&& push_backAşırı sonra movevektör içine geçici s v. Bir std::stringtampon tahsis edilir ve vektöre taşınır. Boş std::stringbir atılır.
Görev
@ Jarod42'nin aşağıdaki cevabından çalındı.
Seçim atama ile gerçekleşemez, ancak geçiş yapılabilir.
std::set<int> some_function();
std::set<int> some_value;
// code
some_value = some_function();
burada some_functionbir adayı elide olarak döndürür, ancak doğrudan bir nesne inşa etmek için kullanılmadığından, seçilemez. C ++ 03'te, yukarıdaki geçici kopyaya kopyalanır some_value. C ++ 11'de, some_valuetemelde ücretsiz olan içine taşınır .
Yukarıdakilerin tam etkisi için, hareket yapıcılarını ve atamayı sizin için sentezleyen bir derleyiciye ihtiyacınız vardır.
MSVC 2013, hareket yapıcılarını stdkaplarda uygular , ancak hareket yapıcılarını türleriniz üzerinde sentezlemez.
Bu nedenle, std::vectors ve benzerlerini içeren türler MSVC2013'te bu tür iyileştirmeler elde etmez, ancak MSVC2015'te almaya başlayacaktır.
clang ve gcc uzun zamandan beri örtük hareket yapıcıları uygulamaktadır. Intel'in 2013 derleyicisi, geçerseniz örtük nesil oluşturucuları destekleyecektir -Qoption,cpp,--gen_move_operations(MSVC2013 ile çapraz uyumlu olma çabasıyla bunu varsayılan olarak yapmazlar).