Atama operatörü ile kopya oluşturucu arasındaki fark nedir?


107

C ++ 'da atama yapıcısı ile kopya oluşturucu arasındaki farkı anlamıyorum. Şöyle:

class A {
public:
    A() {
        cout << "A::A()" << endl;
    }
};

// The copy constructor
A a = b;

// The assignment constructor
A c;
c = a;

// Is it right?

Atama yapıcısının belleğini nasıl ayıracağımı ve oluşturucuyu nasıl kopyalayacağımı bilmek istiyorum?


2
Eğer var mı iyi C ++ kitap ?
sbi

Yanıtlar:


161

Bir kopya yapıcı , önceden başlatılmamış bir nesneyi başka bir nesnenin verilerinden başlatmak için kullanılır .

A(const A& rhs) : data_(rhs.data_) {}

Örneğin:

A aa;
A a = aa;  //copy constructor

Bir atama operatörü , önceden başlatılmış bir nesnenin verilerini başka bir nesnenin verileriyle değiştirmek için kullanılır .

A& operator=(const A& rhs) {data_ = rhs.data_; return *this;}

Örneğin:

A aa;
A a;
a = aa;  // assignment operator

Kopyalama yapısını varsayılan yapım artı atama ile değiştirebilirsiniz, ancak bu daha az verimli olacaktır.

(Bir yan not olarak: Yukarıdaki uygulamalarım, derleyicinin size ücretsiz olarak verdiği tamdır, bu yüzden onları manuel olarak uygulamak pek mantıklı olmaz. Bu ikisinden birine sahipseniz, bazı kaynakları manuel olarak yönetiyor olabilirsiniz. Bu durumda, The Rule of Three'ye göre , büyük olasılıkla diğerine ve bir yıkıcıya da ihtiyacınız olacak.)


4
Sadece bir not: Günümüzde (C ++ 11 sonrası), açıkça varsayılan olarak =default;.
Deduplicator

2
@Deduplicator Önemsiz oluşturucular gerektiren sınıflandırmalara bağlı kalarak, varsayılan bir ctor gerekli olduğunda bunları yapmanız gerektiğini belirtmek de önemlidir = default: boş bir gövdeyi kendi başımıza uygulamak hala kullanıcı tanımlı bir ctor olarak sayılır ve bu nedenle (Standart bir seviyede) ) önemsiz değildir ve türü önemsiz bir ctor gerektiren sınıflandırmalardan çıkarır.
underscore_d

@sbi Kopyala yapıcı kullanılmaması ve bunun yerine atama operatörü kullanılması durumunda önce yapıcıyı argümanlar ile veya argümansız çağırarak nesne oluşturulur ve sonra atama operatörü kullanılır ve RHS'ye göre yeni değerler atanır. Kopya yapıcısının kullanılması durumunda, yine aynı kurucu çağrılacaktır, ancak başlatma için kullanılan değerler başka nesneden alınır.
Rajesh

@Rajesh: Ne sorduğun konusunda kafam karıştı ve benim de kafan karıştığından dolayı. :)Neden bahsettiğini tekrar açıklamaya çalışır mısın?
sbi

1
@ CătălinaSîrbu: Yapabilirsin. İki bağımsız işlevdir.
sbi

42

Kopya yapıcısı ile atama operatörü arasındaki fark, yeni programcılar için çok fazla kafa karışıklığına neden olur, ancak bu gerçekten o kadar da zor değil. Özetleme:

  • Kopyalama gerçekleşmeden önce yeni bir nesnenin oluşturulması gerekiyorsa, copy yapıcısı kullanılır.
  • Kopyalama gerçekleşmeden önce yeni bir nesnenin oluşturulması gerekmiyorsa, atama operatörü kullanılır.

Atama operatörü örneği:

Base obj1(5); //calls Base class constructor
Base obj2; //calls Base class default constructor
obj2 = obj1; //calls assignment operator

Kopya oluşturucu örneği:

Base obj1(5);
Base obj2 = obj1; //calls copy constructor

Bir atama operatörünün eski bir nesnenin yok edilmesini yeni bir nesnenin yaratılmasıyla etkili bir şekilde birleştirdiğini söylemek doğru olur mu, ancak şu şartla (1) eski nesnenin yok edilmesindeki adımlardan biri tarafından geri alınırsa yenisinin yapımındaki adımlardan biri, her iki adım da atlanabilir; (2) atama operatörleri, kendisine bir nesne atanmışsa kötü şeyler yapmamalıdır.
supercat

neden yapıyor vector <A> v3ve sonra v3 = v2 ( v2daha önce bildirilen ve içeren öğeler nerede vector<A>)A bunun yerine benim açıkımın kopya yapıcısını çağırıyor operator=? Bunun operator=yerine çağrılmayı bekliyordum copy constructorçünküv3
nesnem

19

Birincisi kopya başlatma, ikincisi sadece atamadır. Atama yapıcı diye bir şey yoktur.

A aa=bb;

derleyici tarafından üretilen kopya yapıcısını kullanır.

A cc;
cc=aa;

oluşturmak için varsayılan kurucuyu ccve daha sonra operator =zaten var olan bir nesne üzerinde * atama operatörünü ** ( ) kullanır.

Atama yapıcısının belleğini nasıl ayıracağımı ve oluşturucuyu nasıl kopyalayacağımı bilmek istiyorum.

Bu durumda bellek ayırmaktan kastınız IDK, ancak ne olacağını görmek isterseniz şunları yapabilirsiniz:

class A
{
public :
    A(){ cout<<"default constructor"<<endl;};
    A(const A& other){ cout<<"copy constructor"<<endl;};
    A& operator = (const A& other){cout <<"assignment operator"<<endl;}
};

Ayrıca şunlara bir göz atmanızı tavsiye ederim:

Neden dönüşüm kurucusu yerine kopya oluşturucu çağrılıyor?

Üç Kuralı Nedir?


5

Basit bir deyişle,

Copy constructor, mevcut bir nesneden yeni bir nesne oluşturulduğunda, mevcut nesnenin bir kopyası olarak çağrılır. Ve atama operatörü, önceden başlatılmış bir nesneye başka bir mevcut nesneden yeni bir değer atandığında çağrılır.

Misal-

t2 = t1;  // calls assignment operator, same as "t2.operator=(t1);"
Test t3 = t1;  // calls copy constructor, same as "Test t3(t1);"

4

Ne @Luchian Grigore Said böyle uygulanıyor

class A
{
public :
    int a;
    A(){ cout<<"default constructor"<<endl;};
    A(const A& other){ cout<<"copy constructor"<<endl;};
    A& operator = (const A& other){cout <<"assignment operator"<<endl;}
};

void main()
{
    A sampleObj; //Calls default constructor
    sampleObj.a = 10;

    A copyConsObj  = sampleObj; //Initializing calls copy constructor

    A assignOpObj; //Calls default constrcutor
    assignOpObj = sampleObj; //Object Created before so it calls assignment operator
}

ÇIKTI


varsayılan kurucu


yapıcı kopyala


varsayılan kurucu


atama operatörü



4

kopya yapıcısı ile atama yapıcısı arasındaki fark şudur:

  1. Kopya yapıcısı olması durumunda yeni bir nesne oluşturur. ( <classname> <o1>=<o2>)
  2. Bir atama yapıcısı olması durumunda, herhangi bir nesne oluşturmaz, zaten oluşturulmuş nesnelere ( <o1>=<o2>) uygulandığı anlamına gelir .

Ve her ikisinde de temel işlevler aynıdır, verileri o2'den o1'e üye tek kopyalarlar.


2

Bu konuya bir nokta daha eklemek istiyorum. "Atama operatörünün operatör işlevi yalnızca sınıfın bir üye işlevi olarak yazılmalıdır." Diğer ikili veya tekli operatörlerin aksine bunu arkadaş işlevi yapamayız.


1

Kopya oluşturucu hakkında eklenecek bir şey:

  • Bir nesneyi değere göre iletirken, kopya yapıcısını kullanır

  • Bir nesne bir işlevden değere göre döndürüldüğünde, kopya yapıcısını kullanır

  • Başka bir nesnenin değerlerini kullanarak bir nesneyi başlatırken (verdiğiniz örnek gibi).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.