2014-09-24 16 views
11

aşağıdaki iki program çok daha iyi bir performansa sahip ikinci bir ile, farklı çıkışlara derlemek (gcc ve clang ile test):Otomatik xValue Biraz şaşırtıcı (bana) optimizasyon

#include <vector> 
int main() 
{ 
    std::vector<int> a(2<<20); 
    for(std::size_t i = 0; i != 1000; ++i) { 
     std::vector<int> b(2<<20); 
     a = b; 
    } 
} 

vs

#include <vector> 
int main() 
{ 
    std::vector<int> a(2<<20); 
    for(std::size_t i = 0; i != 1000; ++i) { 
     std::vector<int> b(2<<20); 
     a = std::move(b); 
    } 
} 

birisi derleyici yapar göre neden (veya can) otomatik b son atamasında bir xValue düşünün ve açık std::move döküm olmadan hareket semantiğini uygulanamıyor?

Düzenleme: (g++|clang++) -std=c++11 -O3 -o test test.cpp

+0

Derleyicilere ilettiğiniz parametreler nelerdir? – Joe

+1

İlk tahminim, programın anlambilimini bir kopyasını harekete geçirerek beklenmedik bir şekilde değiştireceğidir. – pmr

+0

@pmr: Ben de öyle şüpheliyim, ama nedenini anlamak isterim. Naif olarak, bir xvalue'nun bana olması gerektiği gibi görünüyor. – Xoph

cevap

6

Compilers can't break the as-if rule

olarak §1.9/1 ifade eder: Bu standardın içinde

semantik tanımları parametreli nondeterministic soyut makine tanımlar. Bu Uluslararası Standardı, uygulamalarının yapısına ilişkin bir gereksinim duymaz. Özellikle, soyut makinenin yapısını kopyalamaya veya taklit etmeye ihtiyaçları yoktur. bir derleyici programının gözlemlenebilir davranışı değiştiremez yani

aşağıda açıklandığı gibi yerine, uygun uygulamalar (yalnızca) özet makinenin gözlemlenebilir davranışı taklit etmek için gereklidir. Otomatik olarak (yansıma olmasa bile) bir atamayı bir hareket atamasına dönüştürmek bu ifadeyi bozardı.

Kopyalama kararları bu davranışı biraz değiştirebilir, ancak bu, §12.8/31 ile düzenlenmiştir.

Taşıma sürümünü kullanmak isterseniz, ikinci örnekte olduğu gibi bunu açıkça istemelisiniz.

+1

Tamam, özellikle programcı, güvenilir kopyalama/taşıma operatörü/ctor çağrısı olmalıdır. Programcıların bu işlemleri semantik olarak uyumlu hale getirmelerini gerektirmenin mantıklı olacağını düşündüm. Her iki yaklaşımın da artıları ve eksileri olacağını sanıyorum, ama standardın neden farklı olduğunu görebiliyorum. – Xoph

+2

Bu özel kodda, çıkış-yok kuralı kırılmaz çünkü çıktı yok –

5

ile Derleyen (operator= den void dönüş türü göz ardı edin) sonraki numunenin bakalım:

#include <iostream> 

struct helper 
{ 
    void operator=(helper&&){std::cout<<"move"<<std::endl;} 
    void operator=(const helper&){std::cout<<"copy"<<std::endl;} 
}; 

void fun() 
{ 
    helper a; 
    { 
     helper b; 
     a = b; 
    } 
} 

void gun() 
{ 
    helper a; 
    { 
     helper b; 
     a = std::move(b); 
    } 
} 
int main() 
{ 
    fun(); 
    gun(); 
} 

operator= bağımsız değişkenleri bağlı olarak farklı davranışlar vardır. Derleyici, yalnızca gözlemlenebilir davranışı aynı şekilde koruyabiliyorsa kodu optimize edebilir. o programın gözlemlenebilir davranışı değişecek çağrının yapıldığı andaki bir xvalue değildir ve bu arzu ne de standardına göre izin verilmez iken

, fun bir xvalue den b düşünürsek.

+0

Teşekkürler, kurucu aramadaki değişimin farkındaydım. Programcının bir şekilde müteahhitleri/operatörleri hareket ettirmesi ve kurucuların/operatörlerin "semantik olarak eşleştirilmesi" için bir şekilde gerekli olduğunu varsaydım ve sanırım bu benim kusurum! – Xoph

İlgili konular