2013-04-15 24 views
5

için işaretçiler vektör oluşturmak için:nasıl bir dizisine bir gösterici sahip bir vektör

vector<double> mv; 
mv.push_back(233); 
mv.push_back(234); 
mv.push_back(654); 
vector<double>* new_mv_pt = new vector<double> (3); 
new_mv_pt = &mv;  

cout << (*new_mv_pt)[1] << endl;  

nasıl bir vektör için bu işaretçi saklayacak başka vektör yapabilir? ben ...

vector<double*> vop = new vector<double> (3); 

vop.push_back(*new_mv_pt); 

cout << (*vop)[1] << endl; 

bu çalışıyordu ama işe yaramadı. Ben

+2

İ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ı. –

+0

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. –

cevap

3

Evet ?: bile mümkün çalışılıyor, ama bunu yapmak için gereken ne:

vector<vector<double>*> vop; 

vektör işaretçiler listesi için aradığınız çünkü.

Burada ne var:

vector<double *> vop 

sadece double göstergelerinin bir vektörüdür. Daha sonra adres new_mv_pt öyle saklayarak,

vector<double>* new_mv_pt = new vector<double> (3); 
new_mv_pt = &mv; 

Sen yığın üzerinde vector<double> oluşturuyorsunuz ve: Bir bellek burada sızıntı var

vop.push_back(new_mv_pt); // <- No asterisk (you don't want to de-reference it) 
+0

Bellekte sızıntıdan kaçınmak için her iki göstergeyi silme konusunda nasıl giderim? Yeni_mv_pt dosyasını silmeyi deniyorum ve çalışma zamanında bir çeşit onaylama hatası alıyorum. Sorun ne? –

+0

Her iki işaretçiyi ne demek istiyorsun? new_mv_pt' ve vektördeki birisini mi kastediyorsun? –

+0

Yeni_mv_pt'i işaretçi vektörü olmadan silmeyi denediğimde, işe yaramıyor ve çalışma zamanında bir tür onaylama hatasıyla geliyor. Sonunda hepsini nasıl sileceğimi bilmek istiyorum. –

2

:

Ayrıca sadece bu isteyecektir mv adresi ile hitap üzerine yazarak. vector<double> hala yığın üzerinde var, ancak adresinizi kalıcı olarak kaybettiniz (ve bu nedenle delete için bir yolu yoktur ya da onunla başka bir şey yapamazsınız).

Bu kod:

vector<double*> vop = new vector<double> (3); 
vop.push_back(*new_mv_pt); 
cout << (*vop)[1] << endl; 

vop çünkü Çalışmaz double* s'lik bir vektör olduğunu ve bunu içine bir vector<double> eklemeye çalışıyoruz. Doğru yaklaşım için Ben's answer bakınız.

7

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?

+0

Bu son derece yardımcı oldu. Bana çok şey öğrettin. Çok teşekkür ederim. –

+0

Bu çok basit bir soru için inanılmaz derecede ayrıntılı bir cevaptır. Sizler bir profesyonelsiniz! +1 –

İlgili konular