Soru c ++ örtülü kopya kurucu kopya dizi üyesi değişkeni yapar? [çift]


Olası Kopyalama:
C dizi üyeleri kopya kontrol işlevlerinde nasıl ele alınır? 

Üye değişkeni işaretçi olarak bildirilirse, örtülü kopya oluşturucunun (derleyici tarafından oluşturulan) işaretçiyi kopyalayacağını tahmin ediyorum.

Dizi üyesi değişkenine ne olduğundan emin değilim.

Implicit copy constructor dizi üyesi doğru mu? Atama operatörü nasıl?

Örneğin:

char mCharArray[100];
int mIntArray[100];   

MCharArray mIntArray doğru şekilde kopyalanır mı?


25
2018-04-18 08:19


Menşei




Cevaplar:


Evet ve evet cevabı. Bu aynı zamanda C.'deki yapılar için de geçerlidir.

typedef struct {
    int a[100];
} S;

S s1;
s1.a[0] = 42;
S s2;
s2 = s1;    // array copied

49
2018-04-18 08:21



Umarım cevabın doğrudur. diğer insanların cevabı beni şaşkına çevirir :( - eugene
@Eugene İnsanlar bu işten ağırlaşıyor gibi görünüyor. Cevabım doğru - söylediğim gibi, C tam olarak aynı şekilde çalışıyor. - Neil Butterworth
insanlar bunu daha da ağırlaştırıyorlar çünkü işaretçileri ve referansları içeren, biraz daha karmaşık yapıları açıklamaya çalışıyorlar. Bu sorunun soruyu cevaplamak için gerekli olduğu açık değil, ama diğer cevapların Eugene'nin bunu bilmesini sağlamak için açıkça daha iyi hissettiği kadar yakın. - Tony Delroy
@Tony Maalesef, sizinki dışındaki tüm diğer cevaplar aslında yanlıştır ve sizin anlamanızı zor buldum. Ayrıca strdup kullanımını teşvik etmemiz gerektiğini düşünmüyorum! - Neil Butterworth
Strdup hakkında doğru ... Düşünmeye devam ettim - bunu yeni char [] 'a ve bir kopyasına değiştirmeliyim, fakat fazladan kopyalama adımı bugün çok fazla acı çekiyordu ... std::string. Düzeltmek için beni utandırıyorsun! :-) - Tony Delroy


Sadece mümkün olduğunca açık yapmak için:

struct X
{
    char data_[100];
};

X a, b;
a.data_[10] = 'x';
b = a;
// here, b.data_[n] == a.data_[n] for 0 <= n < 100, so b.data_[10] == 'x'

AMA, potansiyel olarak kötü durum işaretçiler ve referanslar içindir:

struct X
{
    char* data_[100];
};

X a, b;
a.data_[10] = new char[6]; // a character array on the heap
strcpy(a.data_[10], "hello"); // put some text into it...
b = a;
// here, b.data_[n] == a.data_[n] for 0 <= n < 100
//   so b.data_[10] == a.data_[10] == same character array containing "hello"
// BUT...
b.data_[10][2] = 'L';  // change text to "heLlo" via b.data_[10] pointer...
// here, a.data_[10][2] will be 'L' too, as a.data_[10] and b.data_[10] both point
// to the same underlying heap memory returned by new above...
delete[] a.data_[10];  // ok...
std::cout << b.data_[10];  // NOT ok - this memory's been deallocated!
delete[] b.data_[10];  // NOT ok - this memory's (already) been deallocated!

Umarım bu, konuyu yanıltmaya yardımcı olur.

Yapıyı daha "kopyalanabilir" hale getirmenin bir yolunu düşünün:

struct X
{
    X(const X& rhs)
    {
        for (int i = 0; i < 100; ++i)
            if (rhs.data_[i])
            {
               // deep copy of pointed-to text...
               data_[i] = new char[strlen(rhs.data_[i]) + 1];
               strcpy(data_[i], rhs.data_[i]);
            }
            else
               data_[i] = NULL;
    }
    char* data_[100];
};

Burada kopya yapıcıyı yapar X b = a daha güvenli ve daha sezgisel olduğundan, tüm dize verilerinin kendi kopyasını çıkarır ve kopyalanan başka herhangi bir bağımlılığa veya bağlantısına sahip değildir. X nesne, ancak bu daha yavaş ve potansiyel olarak daha fazla hafıza kaybıdır.


6
2018-04-18 09:23





"örtülü kopya oluşturucu (derleyici tarafından oluşturulmuş)" - tüm değişkenler için sığ bir kopya yapar.


0
2018-04-18 08:22



Burada sığ kopya ne demek istiyorsun? soru dizisindeki öğeler sığ kopyalanır? - eugene
Sığ bir kopya, "derin kopya" işaretli veya referans değerlere sahip olmadığı anlamına gelir. Diğer bir deyişle, bir işaretçiyi veya referansı sığ bir şekilde kopyalarsanız, aynı nesneye iki işaretçi veya referansla son verirsin (ve bunu erken ya da iki kez serbest bırakmamaya dikkat etmeniz gerekebilir). Derin kopyalar, sivri uçlu veya başvurulan nesneyi de kopyalayacak / klonlayacaktır, böylece işaretçiyi / başvuruyu içeren nesnelerin, kopyalanan nesneden bağımsız olarak "kendi" kopyaları vardır. - Tony Delroy
@Tony: asıl soru "dizi üyeleri sığ kopyalandı veya dizi için işaretçi kopyalanır mı?" Olarak yeniden ifade edilebilir. Dizinin üyeleri derin kopyalanmış mı diye sormuyorum. - eugene
@Eugene: Bunu düşünmenin en iyi yolu, iki değişkene göre değişir: X a = ...; X b = a;daha sonra, X nesnesi, bu semantik davranışı sağlamazsa (örneğin int, çift, vektörler, diziler, ancak düz işaretçiler veya referanslar DEĞİL), b derin kopyalanmaz. Tam olarak aynı şey, a ve b dizileri ve üye değişkenleri ise doğrudur ve öğe temelinde bir öğe üzerinde uygulanır. Kurallar tutarlı. - Tony Delroy


Evet. Kopya kurucusu ve Atama işleçleri C / C ++'da yerleşik olarak yerleşiktir. Bayt kopyalayarak bayt yaparlar (kod bloatına neden olacağı için daha büyük diziler için iyi değildir). Ayrıca işaretçiyi kopyalar ancak sığ kopya (işaretçi bir yere işaret ediyorsa, kopyalanan işaretçi de aynı konuma işaret eder) olacaktır.


-1
2018-04-18 08:23



Hayır, üye kopyası ile üye olurlar. - Neil Butterworth
@iammilind: "byte by byte by ... daha büyük diziler için iyi değil ... kod bloat neden olur" ... açıkça "büyük" sadece hafif "kod bloat" durumu engeller: derleyici çok küçük diziler performans optimizasyonu olarak döngü. Daha büyük diziler için derleyici bir döngü oluşturacak veya bir işlev çağrısı (memcpy () gibi bir şey yapacaktır, böylece oluşturulan kod miktarı dizi boyutundan bağımsız olarak sabit olacaktır. - Tony Delroy
@Tony, bilgi için teşekkürler. Derleyicilerin bu tür optimize edicilere sahip olduğunun farkında değildim. - iammilind
@iammilind: Rica ederim. Aslında, üye uncasının üye tarafından kopyalandığından bahsetmişken, genellikle dizideki her öğe için kopya yapıcıyı çağıran bir döngü tarafından yapılır, böylece optimizasyon kapalıyken bile sabit boyuttan emin olabilirsiniz. Optimizasyon durumları döngü açma ve / veya işlev çağrısıdır. Şerefe. - Tony Delroy
@Tony, demek ki, eğer "derin kopya" olmak için herhangi bir işaretçi üyemiz yoksa, o zaman kopya kopyalama yürütücülerinden kurtulabiliriz (ve operator =) ve yerleşik uygulamaya güveniyor musunuz? - iammilind