SORU
1 Kasım 2008, CUMARTESİ


Dinamik nesneler dizisi ayrılıyor

Bu yeni başlayanlar bir soru olacak, ama buraya çok uzun zamandır C yapmadım...

Dinamik olarak ayrılan bir dizi içeren bir sınıf var diyelim

class A
{
    int* myArray;
    A()
    {
        myArray = 0;
    }
    A(int size)
    {
        myArray = new int[size];
    }
    ~A()
    {
        // Note that as per MikeB's helpful style critique, no need to check against 0.
        delete [] myArray;
    }
}

Ama şimdi bu sınıfların dinamik olarak ayrılan bir dizi oluşturmak istiyorum. İşte benim geçerli kod:

A* arrayOfAs = new A[5];
for (int i = 0; i < 5;   i)
{
    arrayOfAs[i] = A(3);
}

Ama bu kadar çok esiyor. Çünkü yeni A nesne oluşturulur (A(3) çağrı alır tahrip zaman for döngü tekrarında bitirir, ve bu demek oluyor ki iç myArray A örnek alır delete []-ed.

Benim sözdizimi çok yanlış olmalı sanırım? Önlemek için umuyorum ki overkill gibi görünüyor birkaç düzeltme var sanırım

  • Bir kopyasını oluşturma A için yapıcı.
  • Bu konuda endişelenmenize gerek yok bu yüzden vector<int> vector<A> kullanarak.
  • arrayOfAs A nesneleri bir dizi olmak yerine, A* işaretçiler bir dizi olacak.

Bu sadece dinamik iç dinamik ayırma şeyler bir dizi ayırmaya çalışırken işe yarayan bir sözdizimi var, bazı yeni başlayanlar şey olduğunu düşünürdüm.

(Ayrıca, tarzı eleştiriler C yaptım beri bir süre oldu beri takdir etti .)

Gelecek izleyiciler için güncelleme: Tüm cevapları aşağıda çok faydalıdır. Martin'in örnek kod ve yararlı "4," ama ben gerçekten hepsini okuma öneririz. kural nedeniyle kabul edilmiştir Bazı yanlış, neyin iyi, kısa ve öz ifadeleri ve bazı vectors gitmek için iyi bir yol ne kadar doğru.

CEVAP
1 Kasım 2008, CUMARTESİ


Belli ki standart konteynerlerden birini kullanmak istiyorum bina kaplar için (bir std::vector). Ama bu nesne ÇİĞ işaretçiler içerir, dikkate almanız gereken şeyler için mükemmel bir örnek.

Eğer nesne HAM bir işaretçi varsa, 3 (Şimdi C 11 5 kuralı) kuralı hatırlamamız gerekiyor.

  • Kurucu
  • Yıkıcı
  • Kurucu Kopyalayın
  • Atama Operatörü
  • Kurucu (C 11) Hareket
  • Atama (C 11) Hareket

Bu eğer tanımlı değilse derleyici bu yöntemleri kendi sürümü (aşağıya bakınız) oluşturur çünkü. Derleyici sürümleri HAM işaretçiler ile uğraşırken her zaman faydalı değildir oluşturdu.

Kopya yapıcı düzeltmek için zor bir durum eğer güçlü bir garanti sağlamak istiyorsanız önemsiz olmayan). Atama operatörü kopyala ve deyim içten takas olarak Kopya Kurucu açısından tanımlanabilir.

Aşağıda bir sınıf dizisi için bir işaretçi içeren mutlak minimum tam ayrıntılar için bkz.

Önemsiz olmayan std kullanmayı düşünmelisiniz almak için doğru olduğunu bilerek::vektör yerine tamsayı dizisi için bir işaretçi. Vector (ve genişletmek) için kolay ve tüm sorunları ile ilgili özel durumları kapsar. Aşağıda Bir tanımı ile aşağıdaki sınıf karşılaştırın.

class A
{ 
    std::vector<int>   mArray;
    public:
        A(){}
        A(size_t s) :mArray(s)  {}
};

Senin sorunun bakmak

A* arrayOfAs = new A[5];
for (int i = 0; i < 5;   i)
{
    // As you surmised the problem is on this line.
    arrayOfAs[i] = A(3);

    // What is happening:
    // 1) A(3) Build your A object (fine)
    // 2) A::operator=(A const&) is called to assign the value
    //    onto the result of the array access. Because you did
    //    not define this operator the compiler generated one is
    //    used.
}

Derleyici oluşturulan atama operatörünün hemen hemen tüm durumlar için iyi, ama ÇİĞ işaretçiler oyunda zaman dikkat etmek gerekir. Bu durumda, çünkü bir soruna neden olursığ kopyalayınsorun. Bellek aynı parça için işaretçiler içeren iki nesne ile sona erdi. (3) silmek çağırır döngü sonunda kapsam dışına çıktığında [] işaretçisini üzerinde. Böylece diğer nesne (dizi) şimdi sistemi geri döndü bellek için bir işaretçi içerir.

Derleyici kurucu kopyasını üretti; kopya her üye kopyasını kullanarak değişken kurucu üyesi. Göstericiler için bu sadece işaretçi değeri Kaynak, Hedef nesne (dolayısıyla sığ kopyalama) nesne kopyalanır anlamına gelir.

Derleyici atama operatörü oluşturdu; kopya her üye değişkeni kullanarak üye atama operatörü. Göstericiler için bu sadece işaretçi değeri Kaynak, Hedef nesne (dolayısıyla sığ kopyalama) nesne kopyalanır anlamına gelir.

Bir işaretçi içeren bir sınıf için asgari:

class A
{
    size_t     mSize;
    int*       mArray;
    public:
         // Simple constructor/destructor are obvious.
         A(size_t s = 0) {mSize=s;mArray = new int[mSize];}
        ~A()             {delete [] mArray;}

         // Copy constructor needs more work
         A(A const& copy)
         {
             mSize  = copy.mSize;
             mArray = new int[copy.mSize];

             // Don't need to worry about copying integers.
             // But if the object has a copy constructor then
             // it would also need to worry about throws from the copy constructor.
             std::copy(©.mArray[0],©.mArray[c.mSize],mArray);

         }

         // Define assignment operator in terms of the copy constructor
         // Modified: There is a slight twist to the copy swap idiom, that you can
         //           Remove the manual copy made by passing the rhs by value thus
         //           providing an implicit copy generated by the compiler.
         A& operator=(A rhs) // Pass by value (thus generating a copy)
         {
             rhs.swap(*this); // Now swap data with the copy.
                              // The rhs parameter will delete the array when it
                              // goes out of scope at the end of the function
             return *this;
         }
         void swap(A& s) throws ()
         {
             std::swap(this.mArray,s.mArray);
             std::swap(this.mSize ,s.mSize);
         }

         // C  11
         A(A&& src) noexcept
             : mSize(0)
             , mArray(NULL)
         {
             (*this) = std::move(src); // Implements in terms of assignment
         }
         A& operator=(A&& src) noexcept
         {
             src.swap(*this);     // You are moving the state of the src object
                                  // into this one. The state of the src object
                                  // after the move must be valid but indeterminate.
                                  //
                                  // The easiest way to do this is to swap the states
                                  // states of the two objects.
                                  //
                                  // Note: Doing any operation on src after a move 
                                  // is risky (apart from destroy) until you put it 
                                  // into a specific state. Your object shoudl have
                                  // appropriate methods for this.
                                  // 
                                  // Example: Assignment (operator = should work).
                                  //          std::vector() has clear() which sets
                                  //          a specific state without needing to
                                  //          know the current state.
         }   
 }

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • BiGSH0TROB

    BiGSH0TROB

    7 NİSAN 2011
  • kimaliz

    kimaliz

    18 Temmuz 2006
  • mipd1980

    mipd1980

    25 EKİM 2006