2016-03-21 20 views
0

SO sorusunda [C++ işaretçisinin 2B dizisi nasıl ayrılır] [1], kabul edilen yanıt ayrıca söz konusu diziyi ayırma ve silme, "İçerilen işaretçileri, satır dizilerini ve sütun dizisini tümüyle ayrı ayrı ve doğru sırada silmeye dikkat edin." Bu yüzden, bu 2D dizisini hücresel otomat simülasyon programında başarıyla kullanıyorum. Bununla birlikte, bu dizinin bellek yönetimini doğru yapamıyorum. Yukarıdaki referanstan başka nasıl yapıldığına dair bir SO cevabı göremiyorum. AçıkçaC++ Nesneler için 2B işaretçi dizisi nasıl ayrılır ve silinir

for (int i = 0; i < rows; i++) { 
    for (int j = 0; j < cols; j++) { 
     matrix_0[i][j] = NULL; 
    } 
} 
delete [] matrix_0; 
matrix_0 = NULL; 

:

Object*** matrix_0 = new Object**[rows]; 
    for (int i = 0; i < rows; i++) { 
     matrix_0[i] = new Object*[cols]; 
    } 

My nafile girişimi (ler) uygun bir şekilde de tahsis etme aşağıdaki gibidir yukarıdaki dizi (Valgrind göre) aşağıdaki gibidir:

I 2D dizi tahsis [1], [1] referans olarak satırları ve cols kısmını kaçırıyorum. Neyi kaçırdığımı gösterir misin? Şimdiden teşekkürler.

[1]: (2009 Kasım 20) How to allocate a 2D array of pointers in C++

+6

'std :: vektör >> vector_of_objects;' – SergeyA

+0

2B dizi nesnelere veya 2B işaret dizisine mi dikkat çektiniz? –

+0

@ R Sahu: Sınıf nesnelerini temel alan bir 2B işaret dizisi ve çeşitli hücresel otomatık türetilmiş nesnelerin polimorfik davranışından yararlanmak için bu şekilde ayarlanır. – Chris

cevap

5

Bunda yapmak silinmesinin bir ton vardır: sonra gitti çünkü matrix_0 hariç NULL şey gerek yoktur

for (int i = 0; i < rows; i++) { 
    for (int j = 0; j < cols; j++) { 
     delete matrix_0[i][j]; // delete stored pointer 
    } 
    delete[] matrix_0[i]; // delete sub array 
} 
delete [] matrix_0; //delete outer array 
matrix_0 = NULL; 

silin.

Bu, korkunç ve gereksizdir. Use a std::vector ve içerilen nesneye işaretçiyi yeniden gözden geçirin. Hız OP'ın hedeflerinden biridir yana

std::vector<std::vector<Object*>> matrix_0(rows, std::vector<Object*>(cols)); 

istediğini alır ve

for (int i = 0; i < rows; i++) { 
    for (int j = 0; j < cols; j++) { 
     delete matrix_0[i][j]; // delete stored pointer 
    } 
} 

Ama unique_ptr depolama Sergeya önerisine silme işi azaltır, std::vector<std::vector<std::unique_ptr<Object>>> matrix_0; 0.

için gerekli silmeleri azaltır Daha bir iyileştirme var:

Erişim Bu görünmez matematik ve işaretçi dereferences şu anda perde arkasında neler görebilir matematik biraz esnaf

matrix_0[row * cols + col]; 

olduğunu. Önemli olan, vektörün, günümüzde uzaysal alanın arttırılması ve önbellek kayıplarının sayısının azaltılması için güzel bir bitişik bellek bloğu olarak depolanmasıdır. Objects işaretçisinin bellekte dağılmasından kaynaklanan hatalar konusunda yardımcı olamaz, ancak her zaman kazanamazsınız.

vector vs dizisindeki bir not.

std::vector<std::unique_ptr<Object>> matrix_0(rows * cols); 

hepsi vector olduğunu sonunu işaretlemek için bir ve bir çift diğer işaretçiler bir işaretçi ve son konumudur: Bir vector inşa edildikten sonra, ve bu durumda hepsi burada tek seferde bitti konum kullanıldı. Veri dizisine erişim, new ile yapılan dinamik diziye erişimden farklı değildir. [] dizin operatörünün kullanılması, bir dizide data_pointer + index tam olarak []'u kullanarak aynıdır.Java'nın Vector'deki gibi bir senkronizasyon veya benzeri yoktur. Sadece düz ham matematik.

Dinamik bir dizi ile karşılaştırıldığında, tüm önceden ayrılmış bir vector maliyeti, iki değerindeki bellek değerine eşittir ve karşılığında bellek yönetimindeki sıkıntılara yakın olursunuz.

+0

Evet, korkunç ama gerekli yapılmış, "hız" endişeleri ile söylendi. Doğru ve test edilmiş cevabınız için teşekkür ederiz. – Chris

+1

Bu ve "std :: vector >" arasındaki hız farkı, vektörlerinizi oluştururken yeterli alan ayırırsanız "algılanamaz" ve "ihmal edilebilir" arasında bir olasılıktır. –

0

İşaretçileri NULL olarak ayarlamadan önce, önce bunları delete yapmalısınız. Sütundaki her işaretçi silindikten sonra, delete[] satırını atabilir ve her öğe silinip gider olarak NULL olarak ayarlayabilirsiniz.

İlgili konular