2012-09-16 14 views
6

, ben üye değişkeni std::vector<node*> childrenİşaretçiyi bir işaretçi vektörüne itmek için bir bellek sızıntısı mı? Benim sınıfımda

Aşağıdaki sınıf üyesi işlevi bellek sızıntısı oluşturuyor mu var?

//adds a child node 
{ 
    node* child = new node("blah","blah","blah"); 
    child->Set_Parent(this); 
    children.push_back(child); //<- Is this ok? 
} 

vektör pointer bir kopyasını oluşturur ve aynı bellek, iki işaretçiler ve daha sonra orijinal işaretçi doğru, kapsam dışına gider?

Bu basit ve açık olabilir, ancak yalnızca varsayımımı onaylamak isterim.
teşekkürler

+1

['std :: shared_ptr'] (http://en.cppreference.com/w/cpp/memory/shared_ptr) gibi akıllı işaretçilere bakmanızı öneririm. –

+3

@JoachimPileborg: Bu durumda, std :: vector, semantikleri taşıdığı için, ['std :: unique_ptr'] (http://en.cppreference.com/w/cpp/memory/unique_ptr) seçeneğini de kullanabilirsiniz. – bitmask

+0

Düğümlerin her zaman ebeveynleri olması gerekiyorsa, bunu yapıcının bir parçası haline getirebilirsiniz. O halde tek (,), bu "blah" Yeni düğümü ("blah", "blah") 'children.push_back gerekir,' – dtech

cevap

12

Bu bir sızıntı değil ... henüz. Bununla birlikte, vector kapsam dışına çıkarsa veya erase, pop_back veya vektörlerden öğeleri kaldıran başka bir şey yaptıktan sonra, kaldırdığınız öğenin ilk kez delete elinizde sızıntısı olur.

Bunu yapmanın doğru yolu, vector<node *> ile vector<unique_ptr<node>> arasında değişiklik yapmaktır. Kodunuz

//adds a child node 
{ 
    node* child = new node("blah","blah","blah"); 
    child->Set_Parent(this); 
    children.push_back(std::unique_ptr<node>(child)); 
} 

değiştirmek Yoksa Boost'u kullanabilirsiniz eğer boost::ptr_vector<node> kullanacaktır.

+0

Evet, ham işaretçilerden kaçınabildim, ancak bellek sızıntılarını izleme pratiğini yapamadım! :) Boost'un böyle bir dersi olduğunu bilmiyordum! teşekkürler –

+4

Son satır sadece 'children.emplace_back (child); –

2

Bu vektörün yıkıcı içeren sınıf çağrıldığında Eğer çocuk düğümü ayırması unutursanız sadece bir bellek sızıntısı var.

+1

kökünü oluşturduğumda nullptr'dan geçeceğim! teşekkür ederim. Evet, yıkıcım vektörün içinden geçer ve her bir işaretçiyi siler. İşaretçileri kısa bir süre sonra yok olacağından, onları null olarak ayarlamak için bir neden bulamıyorum. –

1

Bu bir bellek sızıntısı değil. Vektörde hala bir işaretçiniz var ve gerektiğinde hafızayı kaldırabileceksiniz.

1

Vektör kapsam dışına çıktığında, yıkıcı sivri nesneyi yok etmiyor. İşaretçiyi yok eder - hiçbir şey yapmaz.

Kodunuz, new aracılığıyla bu nesneyi oluşturdu. Bu nesneyi silmek için kodunuz sorumludur. Eğer bunu yapmazsan, bir sızıntın var. Bunu erken yapmak için yaparsanız, yani, işaretçiyi vektörden çıkarmadan önce, daha da büyük sorunlarınız vardır.

-3

children'un bir sınıf üyesi olduğunu varsayarak, sınıf deconstructor'daki vektörteki tüm öğeleri silebilirsiniz.

struct Foo{}; 

class Bar 
{ 
public: 
    Bar(){}; 
    ~Bar() 
    { 
     for(vector<Foo*>::iterator it = children.begin(); it != children.end(); ++it) 
     { 
      SAFE_DELETE((*it)); //use your own macro/template or use delete if you don't have one 
      delete (*it); 
      (*it) = NULL; 
     } 
    } 
    vector<Foo*>children; 
} 

Foo* p = new Foo(); 
children.push_back(p); 

Bir new hiçbir nesne öbek üzerinde tahsis bu durumda, vector<Foo>child yerine, özgün nesnenin bir kopyasını yaratacak vektör üzerinde her push_back saklanmasına, ancak işaretçileri kullanıyorsanız beri kullandıysanız kopya oluşturulur, uzun ömürlü bir nesneye işaret eden işaretçi basitçe saklanır, yani evet, daha sonra silmeniz gerekir.

+0

Bu mantıklı.Bütün nesne yok edileceği için onları null olarak ayarlamam gerektiğini düşünmüyorum. Makro/şablonun amacını anlamıyorum. –

+1

Doğru anlamadım, Silmek için NULL'e bir işaretçi ayarlamanız gerektiğini düşünmüyor musunuz? 'safe_delete', çağlar için bilinen bir makro/şablon olmuştur, amacı güvenli bir şekilde tahsis edilen bir öğeyi silmektir. David Mayhew ve Scott Meyers'den etkili/etkili C++ okumayı öneririm. –

+4

Downvoter değilim, ama bu aptalca. 'SAFE_DELETE' güvenli değil; Tüm yaptığı, "delete" i çağırmadan önce işaretçinin boş olup olmadığını kontrol etmektir. Boş bir işaretçiyi silerken yanlış bir şey yok. Bu teste gerek yok; sadece 'delete' kullanmak yerine 'SAFE_DELETE' kullanılmasına gerek yoktur. SAFE_DELETE'i gerçekten güvenli hale getirmek için bir şekilde null olmayan bir işaretçinin "delete" i çağırmadan önce "new" ile gerçekten tahsis edilip edilmediğini kontrol etmek gerekir. Bunu yapmıyor. İşaretçiyi sildikten sonra 'NULL' olarak ayarlamak için de bir neden yok; yok ediciyiz. –

İlgili konular