Dur orada yavaşla!
Belleğinizle oldukça çılgın şeyler yapıyorsunuz, o yüzden baştan başlayalım.
İçinde 3 öğeler barındıran bir tek vektör var. Bir işaretçi kullanarak vektöre başvurmak istersiniz. Bakalım nasıl görünüyor:
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// No no no no! You don't have to `new` a pointer that
// you're going to assign to something else!
// This is called a memory leak, and it means you've just wasted (!!!)
// C++ memory! Don't do it
// vector<double>* new_mv_pt = new vector<double> (3);
// Instead, do this:
vector<double>* ptr_to_mv = &mv; // No leak, immediately points to a vector<double> mv;
Bu ilk bit ile ilgilenir. Şimdi, biraz daha derine inelim. Vektörlere referansların bir vektörünü saklamak istersiniz. Tamam, bu adil görünüyor. Bununla ilgili birkaç yol var.en mv
örneğinde ve diğer şeyler dönelim: Kodunuzdaki Bu noktada
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
vector<double>* ptr_to_mv = &mv;
// So far so good. Now, based on your question, you want
// to have a list of these to point to. So:
vector<vector<double>*> vop;
vop.push_back(ptr_to_mv); // All clean.
, o zaman bunun KQUEUE *
veya kullanımı ile bir vector<double>*
almak için .at()
veya operator[]
ile vop
erişmek zorunda ->
doğrudan üzerinde çalışmaya: bunların hepsi en mv
başvuran çünkü
std::vector<double>* ptr_to_vector = vop[0]; // Got my pointer
std::cout << ptr_to_vector->at(0) << std::endl; // Prints '233'
Bu 233 yazdırır. Başka bir cevaba yapılan bir yorumda, bu işaretçileri sildiğinizde, bir iddia aldığınızı söylemiştiniz. Bunun olması gerekiyordu, çünkü ikişer şeyi siliyorsunuz!
Uzun bir zaman önce ilan ettiği, mv
hatırla Eh, bunun dinamik bir vector.You new
bunu yapmadı yapmadığını ve hiçbir işaretçi bu. fonksiyon çıkar Yani zaman, otomatik olarak kendini silecektir - bu yığının üzerindeki yıkıcı ve ölmesine arayacak. Eğer ptr_to_vector
veya ptr_to_mv
bakarsak, hepsi kendini temizler, hangi mv
durumdayız.
Üzerinde silme işlemini çağırırsanız, mv
numaralı telefondan silme çağrısında bulunuyorsunuz (işaret ettiğin şey budur) ve çift siliyorsunuz! Eğer mv
için bir işaretçi varsa
yüzden, silmeyin. Yığın tabanlı bir değişken. Kendini temizleyecek.
Hala şu? Büyük, şunu içine almak biraz daha bakalım: Şimdi , sana daha önce söylemiştim gibi (bir vektör, yaşlı bir işaretçi ile geçersiz atamazsanız kadar new
gerek bir sebebi varsa, hafızayı bırakacaksınız). bu sadece çünkü biz, hem değil başka biri, silme arayarak kadar temizlenmesi gereken vop
, iç ve 2 işaretçiler var:
// Our vector of double vector pointers
vector<vector<double>*> vop;
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// References a stack variable: don't delete
vector<double>* ptr_to_mv = &mv;
vop.push_back(ptr_to_mv);
// Makes a fresh copy of mv. You must delete this
// manually
vector<double>* fresh_ptr = new vector<double>(mv);
(*fresh_ptr)[0] = 1337;
// changes only data in fresh_ptr, not `mv`
vop.push_back(fresh_ptr);
/* Blah blah blah, work */
// Functions about to exit, gotta clean up!
delete fresh_ptr;
//delete ptr_to_mv; // NO.
//delete vop[0]; // NO!
//delete vop[1]; // ... Already deleted from fresh_ptr
// ... This is going to get tedious if we don't have a fresh_ptr
// for every vector we need!
yukarıda sorunu gösterir: Sen tamamen yepyeni bir işaretçi yapmak otomatik olarak temizleyen mv
referansı! Vektör üzerinde döngü yapmak ve herşeyi silmek, o iğrenç iddianın gerçekleşmesine neden olacaktır. Bununla nasıl baş edeceğiz ve ihtiyacımız olan temizliği nasıl yapacağız?
Kirli ve Hızlı Çözüm 1 yalnızca delete vop[1]
/fresh_ptr
içindir ve bununla bitmelidir. Daha iyi bir çözüm Bir kaynak yukarı new
zaman, bir std::unique_ptr
denen bu harika bir şey içinde tamamlamayı, olmasıdır. Kod aşağıdaki gibi görünecektir: Gittiğiniz orada
// Our vector of double vector pointers. Non-owning
vector<vector<double>*> vop;
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// References a stack variable: don't delete
vector<double>* ptr_to_mv = &mv;
vop.push_back(ptr_to_mv);
// Makes a fresh copy of mv
// puts it inside a std::unique_ptr,
// which, like a stack-based vector,
// can clean itself up
std::unique_ptr<vector<double>> fresh_ptr(new vector<double>(mv));
vop.push_back(fresh_ptr.get());
/* Blah blah blah, work */
// Functions about to exit, gotta clean up!
//delete fresh_ptr; // Not necessary
//delete ptr_to_mv; // Nope.jpg
Ve bütün olduğu yorumunu aşımı kodu kaldırmak ve aniden, eşyalarını bir ıslık gibi temiz!
Şüphesiz, şimdi, senin için var son soru: Buna ne yaptığını vektörlerin işaretçileri referanslarına işaretçiler tüm bu işaretçileri gerektirir?
İlk olarak, cevabınızı alın. İkincisi, bunun korkunç bir fikir olduğunun farkındasınız, çünkü vektörün sizin için belleği yönetme yeteneğini ortadan kaldırıyorsunuz. Bu, en azından ilk etapta onu kullanmanın en büyük noktası. –
Sadece neden bir vektörün bir işaretçisine neden olduğunu anlamaya çalışıyorum. Bunu, özellikle de aynı işlevde/sınıfta olsaydı, böyle yapmak için kavramsal bir anlam ifade etmez. –