2016-08-08 8 views
5

Ben Madde 11 benim atama operatörü içinde "kopyalama ve takas" tekniğini kullanmaktır öneren olduğu "Scott Meyers tarafından Etkili C++", okuyordu:kopyalama ve takas tekniği atama operatörü işlevi içinde kopya kurucu kullanır

Widget& Widget::operator=(const Widget &rhs) 
{ 
    Widget temp(rhs); // Copy constructor 
    swap(temp); //Swap with *this 
    return *this; 
} 

Ama Item 12'de yazılıdır:

Bu kopya atama operatörü kopya kurucu çağırmak için hiçbir mantıklı.

Öğe 11 ve Öğe 12'nin çelişkili olduğunu düşünüyorum. Yanlış anlıyor muyum?

+0

You Muhtemelen bunu bağlam dışı okuyor. – LogicStuff

+4

Bu kod, derleyicinin bir kopyasını oluşturmasına veya taşımasına izin vererek, pass-by-value kullanmalıdır. –

+1

@BenVoigt Evet 'pass-by-value' başka bir tekniktir ancak bu da doğrudur. – EmptyData

cevap

-7

Tam tersini yapıyorum. Atama operatörüne "derin" bir kopya yapmak için aşırı yük veriyorum (yani, dinamik belleği dikkate aldığınız ve yeni kopyaları buna göre başlatacağınız anlamına gelir). Ardından kopya oluşturucudaki atama işlecini kullanın. Metninize yorum yapamayacağım çünkü o kitabım yok.

Widget::Widget(const Widget& existing) : dynamicThingie(0) 
{ 
    *this = existing; 
} 


Widget& Widget::operator=(const Widget& existing) 
{ 
    a = existing.a; 
    b = existing.b; 

    delete dynamicThingie; 
    dynamicThingie = new Thingie(); 
    memcpy(dynamicThingie, existing.dynamicThingie, lengthOfDynamicThingue); 

    return *this; 
} 
+4

İstisna göre güvenli değildir ve kopya ctor'da üyelerin varsayılan başlatılmasını zorlar. –

+0

OP kodu, bütünüyle atılan yerel bir nesne oluşturur, nasıl daha iyi olduğunu göremiyorum.Daha az verimli bile olabilir. OP kodu da istisna olarak daha güvenli görünmüyor. –

+1

Temel olarak, bir kopyalama görevlendirmesi operatörünün (1) mevcut kaynakları temizlemesine, ardından (2) argümanın içeriğini kopyalamasına ihtiyaç duyar. Bir kopya kurmacasının sadece adım (2) yapması gerekiyor ve adımı (1) yapmak gerçekten kötü bir şey olurdu çünkü temizlenmesi gereken bir şey yok. Bu nedenle, ödev operatörünün kopyalama kurucusunu kullanması daha güvenlidir, başka bir şekilde değil. Kopyala ve takas tekniği yeni bir nesne yapar, ancak bunu yapmak aslında oldukça ucuzdur - kopyayı (veya taşıma) yapıcı tarafından başlatılır, bu kopyayı yapar ve yeni nesne doperi tüm temizleme işlemlerini yapar. – templatetypedef

3

"Etkili C++ tarafından Scott Meyers" in 2 atıfta yer aldığı 2 farklı yönü ele alınmıştır.

  • Öğe 11'deki kod parçasında Scott, atama işlecini gerçekleştirmenin yollarından birini gösterir.
  • Öğe 12'de, atıf yaptığınız atıf, atama operatörü ve kopya yapıcısı arasında kod çoğaltmasından kaçınılmasıyla ilgilidir.

iki kopyalama fonksiyonları genellikle benzer organları olacak ve bu bir fonksiyon diğer çağırmasını sağlayarak kod tekrarını önlemek için denemek için sizi baştan olabilir: alıntının üstünde bir paragraf diyor. Madde 12 bu kısmı benim anlayış

şu şekildedir: Aşağıda gibi bir şey yazmaya çalışırsanız (kopyalama atama operatörü görüşmesi kopya yapıcı olması) o zaman yanlış olur:

PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs) 
: Customer(rhs), // invoke base class copy ctor 
    priority(rhs.priority) 
{ 
    logCall("PriorityCustomer copy constructor"); 
} 

PriorityCustomer& 
PriorityCustomer::operator=(const PriorityCustomer& rhs) 
{ 
    logCall("PriorityCustomer copy assignment operator"); 
    this->PriorityCustomer(rhs); // This line is wrong!!! 
    return *this; 
} 
İlgili konular