17

Bu program içinC++ Kurucu, zamansal ve kopya semantiği kopyalayın

#include <iostream> 
using std::cout; 

struct C 
{ 
    C() { cout << "Default C called!\n"; } 
    C(const C &rhs) { cout << "CC called!\n"; } 
}; 

const C f() 
{ 
    cout << "Entered f()!\n"; 
    return C(); 
} 

int main() 
{ 
    C a = f(); 
    C b = a; 

    return 0; 
} 

elde ettiğim çıktı:

Entered f()! 
Default C called! 
CC called! 

f() değere dönüldüğü için geçici olarak geri dönmelidir. Xzx38 T a(x); olduğu gibi, a yapımı için kopya kurucusunu, argümanı olarak geçici olarak geçmesiyle değil mi?

cevap

14

f() değeri döndüğünden, geçici olarak döndürülmelidir. T a = x;, T a(x); olduğu gibi, a yapımı için kopya oluşturucuyu, argümanı olarak geçici olarak iletilmiş olarak çağırmaz mı?

Dönüş Değeri Optimizasyonuna bakın. Bu varsayılan olarak açıktır. Eğer Windows üzerinde MSVC 2005+ kullanıyorsanız, bunu kapatmak ve istenen sonucu elde etmek için /Od'u kullanabilirsiniz (veya GCC'de -fno-elide-constructors). Ayrıca, MSVC için this makalesine bakın.

12,8 kopyalama sınıf nesneleri

belirli kriterler karşılandığı zaman, bir uygulama bir sınıf nesnesi kopya inşaat, ihmal bırakılır bile kopya yapıcı ve/veya Nesne için destructor yan etkileri var. Bu gibi durumlarda, uygulama kaynağı ve ait olarak basitçe iki farklı yolu aynı nesneye atıfta ihmal kopyalama işleminin hedef davranır ve bu nesnenin imha adlı iki kez sonradan meydana geldiğinde iki nesneleri optimizasyon olmadan yok edilmiştir.115 kopya operasyonların Bu elision ( ortadan kaldırmak için kombine birden kopya olabilir) aşağıdaki durumlarda izin verilir:

- Bir sınıf dönüş türüne sahip bir işlevinde bir dönüş açıklamada , sentezleme ile doğrudan işlevin yeniden içine işlev dönüş türü olarak aynı ev-niteliksiz tip bir uçucu olmayan otomatik nesne, kopyalama işlemi otomatik nesne inşa tarafından ihmal edilebilir adıdır değeri edecek - işlenen uçucu olmayan otomatik nesne adı olduğunda, bir taç ifadede, durum nesnenin (15.1) için İşlenenden kopyalama işlemi otomatik oluşturarak atlanabilir istisna nesnesi

doğrudan nesne - bir referansa bağlı edilmemiş bir geçici sınıf nesnesi (12.2) bir sınıf nesnesine aynı cv-niteliksiz türünü kopyalanmış olacaktır , kopya operasyontarafından ihmal edilebilir ihmal kopya

hedefi doğrudan geçici nesne inşa - bir istisna işleyicisi (Madde 15) istisna deklarasyonu ( cv yeterlik hariç aynı türde bir nesne beyan zaman) özel nesne (15.1) halinde, kopyalama işlemi anlamı programı kurucular yürütülmesi için dışında değişmeden ve eğer için bir takma durum nesne durum-beyan işlenmesiyle atlanabilir istisna beyanı olan tarafından bildirilen nesne için yıkıcılar.

Not: Vurgu benim ben return value optimization denir inanıyoruz

+0

Ben GCC kullanın ve '-fno elide-constructors' ile kaput altında neler olduğunu tam olarak gösterdi! Bazen bu optimizasyonlar bir öğrenciyi çok karıştırıyor :) Ancak, varsayılan olarak AÇIK olmaları gerektiğine katılıyorum, çünkü yine de bilgisiz bir kişinin yapısı varsayılan olarak optimize edilecektir. – legends2k

+0

@ legends2k: RVO, kullanıcıların kaprislerine bırakılmayacak kadar kullanışlıdır.Dahası, bu standardın bir optimizasyona izin verdiği çok az örnekten biridir. Bu, neden bırakıldığını yeniden canlandırıyor. Ancak, bunun genel olarak diğer optimizasyonlar için geçerli olmadığını unutmayın. – dirkgently

+0

Anlaştık, gelinen nokta. Wiki bağlantısı için – legends2k

4

Bu, derleyicinizin desteklediği Dönüş Değeri Optimizasyonu (RVO) özelliklerinin bir örneğidir. Bir kopya kurucusu , değere döndüğünüzde çağrılmayabilir.

Bu özelliği kapatmak için GCC'de -fno-elide-constructors seçeneğini kullanın.

+0

+1; – legends2k

2

. f() döner amacı, bu nedenle herhangi bir kopya C a başlatmak için gerekli olan arama yöntemi yığın alanı tahsis edilir nesne C zaman

I varsayalım. Bu senin default C called.

C b = a 

Bu nedenle bir kopya kurucu sizin CC called neden olur.

Btw, wiki'deki örnek, kodunuza çok benziyor. Hızlı yanıt için

+0

+1. Hata! Adlandırma bile benzer görünüyor, ama yemin ederim ki bunu okuduktan sonra yayınlamadım, C++ _'da _Thinking okuyorum :) – legends2k

İlgili konular