2011-03-04 2 views
5

BenBir kopyayı aşırı operatörlerle döndürme

Foo Foo::operator+(const Bar &b) 
{ 
    Foo copy = (*this); 
    if (someCondition) return copy; 
    //snip 
} 

Benim için aşağıdaki gibi bir operatöre aşırı yüklediğim bir Foo sınıfına sahibim: Bu makul görünüyor. Ancak, her ne zaman bir kopyasını iade ettiğimde, Visual Studio beni 'yığının bozulmasından kaynaklanabilecek' bir hatadan uyarır. Yaptığım şeyle ilgili bir sorun mu var?

düzenleme: daha fazla bilgi ile güncelleme.

Hata iletisi:

Windows, sample.exe dosyasında bir kesme noktası tetiklemiştir.

Bu, sample.exe dosyasında bir hata ya da yüklü olan herhangi bir DLL dosyasını gösteren yığınının bozulması olabilir.

Bu, örnek odağı varken kullanıcı F12 tuşuna da bağlı olabilir.

Çıkış penceresi daha fazla teşhis bilgisine sahip olabilir.

Foo::Foo(const Foo&p) 
{ 
    some_pointer = p.get_some_pointer(); 
    some_value = p.get_some_value(); 
} 

Bu kod koptuğunda:

//within dbgheap.c 
    extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(
      const void * pUserData 
      ) 
    { 
      if (!pUserData) 
       return FALSE; 

      if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE)) 
       return FALSE; 

      return HeapValidate(_crtheap, 0, pHdr(pUserData)); 
    } 
+4

Bize Foo'nun kopya kurucusunu gösterir misiniz? –

+1

Hata kodu nedir? – metdos

+0

@ Space_C0wb0y @metdos Daha fazla bilgi ile güncelledim – socks

cevap

3

aynı işaretçi ya da bazı daha anlaşılmamış durumlarla (bir yığından edinme ve farklı bir yığına bırakma, ancak muhtemelen buradaki durum bu değil).

Yapacağım ilk şey yıkıcılara bakmak ve sığ kopyalama ve iki kez silmediğinizi kontrol etmektir. Aşağıdaki kod ile Örnek: Bu durumda

// buggy!!! 
struct test { 
    int * data; 
    test() : data(new int[5]) {} 
    ~test() { delete [] data; } 
    test(test const & rhs) : data(rhs.data) {} 
    test& operator=(test const & rhs) { 
     data = rhs.data; 
    } 
}; 
int main() { 
    test t1;   // 5 ints allocated int t1.data 
    test t2(t1); // no memory allocated, t2.data == t1.data 
} // t2 out of scope: t2.~test() => delete t2.data 
    // t1 out of scope: t1.~test() => delete t1.data but both are the same: double delete 

, size sığ kopyaları veya derin kopyalarını yapmak istediğinize karar verebilirsiniz. İkinci durumda, kopya kurucusu (ve atanma operatörü) kendi belleğini ayırmalı, ikinci durumda ise belleğin iki kez serbest bırakılmamasını sağlamalısınız.

Her zaman işaretçilerle olduğu gibi, kaynak yönetimini harici (önceden oluşturulmuş) sınıflara devretmek daha iyidir. Benzersiz sahiplik (ve derin kopyalar) durumunda, muhtemelen std::auto_ptr (veya C++ 0x'da std::unique_ptr - veya yükseltme varyantları) kullanmalısınız. İkinci durumda, boost::shared_ptr (veya C++ 0'da std::shared_ptr) kullanılarak, verilerin paylaşıldığından ve yalnızca bir kez silindiğinden emin olun.

+1

Ve eğer sınıf, işaretçinin işaret ettiği nesneyi sahip değilse, bir referansı tercih edin. –

+1

@Space: Sınıfı atanabilir olmayan (muhtemelen bir aritmetik işleçleri olan bir sınıf için garip olurdu) verimli bir hale getirecek bir tercih ... – visitor

+0

@visitor: Doğru, bunu dikkate almadı. –