2010-12-18 27 views
9

Tôi có nhiều mã nơi tôi xóa các vùng chứa vector có con trỏ trong đó, nghĩa là tôi phải xóa tất cả các con trỏ trước và sau đó xóa vùng chứa. Mỗi lần tôi lặp lại và xóa các con trỏ theo cách thủ công (tôi biết về stl :: algorithm for_each). Để phá vỡ tất cả mã đó, tôi đã tạo một mẫu để xóa tất cả các vùng chứa vector có con trỏ. Càng xa càng tốt.Xóa bất kỳ vùng chứa nào bằng cách sử dụng các mẫu

Bây giờ, tôi có thêm một số loại vùng chứa bao gồm bản đồ, container đồng thời, v.v. với cùng chức năng cuối cùng khi việc xóa đi. Hàm DeleteContainer(std::vector<T*>& VecIn) mà tôi chỉ có thể làm việc trên các vectơ như đã đề cập ở trên. Có cách nào để làm cho nó đủ chung chung để làm việc trên tất cả các container?

EDIT: Cảm ơn tất cả câu trả lời, tôi ước tôi có thể chọn nhiều câu trả lời. Đối với bất kỳ ai tình cờ gặp câu hỏi này, hãy đọc tất cả câu trả lời và không chỉ câu trả lời được chọn vì tất cả họ đều cung cấp thông tin tuyệt vời.

Trả lời

7

Bạn đã có một câu trả lời hợp lệ, nhưng chỉ để cung cấp một sự thay thế, tôi tin rằng bạn nên xem xét sử dụng Boost Pointer Container và để cho nó xử lý quản lý bộ nhớ:

thư viện này do đó cung cấp chuẩn như containe rs dành cho lưu trữ các đối tượng được phân bổ heap hoặc nhân bản (hoặc trong trường hợp bản đồ, đối tượng được ánh xạ phải là một đối tượng được phân bổ heap hoặc nhân bản vô tính). Đối với mỗi thùng chứa tiêu chuẩn có con trỏ tương đương container mất quyền sở hữu đối tượng theo cách an toàn ngoại lệ .

3

Bạn chỉ có thể sử dụng boost::shared_ptr<T> insted của T* và sẽ không có lý do của DeleteContainer. Nhưng nếu bạn không muốn làm điều này, bạn có thể làm một cái gì đó như thế này

template<class T> 
void DeleteContainer(typename T::iterator begin, typename T::iterator end) 
{ 
for(;begin!=end;++begin) 
    delete *begin; 
} 

sau đó bạn chỉ có thể gọi nó cho bất kỳ container STL bạn muốn theo cách này:

std::some_container<int*> s; 
DeleteContainer<std::some_container<int*> > (s.begin(), s.end()); 
+0

Đây không phải là rất C++ ish. Vùng chứa không phải là ngoại lệ an toàn vì bạn đang gọi trình gỡ rối theo cách thủ công. Bạn cần bọc container trong đối tượng ab để RAII thực sự gọi hàm này tự động khi vùng chứa nằm ngoài phạm vi. –

+0

Nhận xét giống như câu trả lời khác, bạn phải xử lý các vùng chứa liên kết khác nhau. – Nim

4

Tôi sẽ lần thứ hai nhiều người và avise sử dụng shared_ptr hoặc thúc đẩy các thùng chứa con trỏ. Tuy nhiên, bạn có thể viết

template <typename Iter> 
void delete_pointers(Iter begin, Iter end) 
{ 
    for (; begin != end; ++begin) delete *begin; 
} 

Cách sử dụng:

std::vector<Foo*> v; 

// Initialize Foo objects 

delete_pointers(v.rbegin(), v.rend()); 

tôi sử dụng rbeginrend thay vì beginend bởi vì đôi khi, người ta muốn đối tượng được xóa theo thứ tự ngược lại chúng được tạo ra.

Bạn cũng có thể làm

void destroyFoo(Foo* x) { delete x; } 

std::for_each(v.rbegin(), v.rend(), &destroyFoo); 

hoặc sử dụng C++ 0x lambdas.

+0

Chỉ có bình luận tôi sẽ thêm là bạn phải xử lý các thùng chứa liên kết khác nhau, vì bạn không thể gọi xóa trên 'cặp'. – Nim

+0

@Nim: rất tốt. Bạn không thể lặp lại các khóa hoặc giá trị dễ dàng với bản đồ C++, bạn phải viết một bộ điều hợp "second_iterator". –

+0

Sẽ :: toán tử xóa chỉ deallocate bộ nhớ hoặc nó cũng sẽ gọi destructor? Tôi có những nghi ngờ của tôi ở đây ... – Tomek

0

Cách khác là từ bỏ hoàn toàn việc xóa và cam kết sử dụng bộ thu gom rác :) Bạn có thể thử bộ thu Boehm-Reiser-Detlefs, tiêu chuẩn trên Linux (libgc) và được sử dụng trong nhiều chương trình phức tạp bây giờ (chẳng hạn như gcc). Nó cũng là một ý tưởng tốt để từ bỏ RAII: đó là một ý tưởng hay vào thời điểm đó nhưng nó không hoạt động tốt trong thực tế. Nhiều tài nguyên được tạo ra một cách độc lập và bị phá hủy theo thứ tự với sự đại diện của chúng.

0

Đưa tôi về vấn đề này sẽ là:

template<class T> 
void Destroy(T *p) 
{ 
    delete p; 
} 

template<template<typename, typename> class C, typename T1, typename T2> 
void Destroy(C<T1 *, T2> &c) 
{               
    std::for_each(c.begin(), c.end(), Destroy<T1>); 
} 

Thử nghiệm trên g ++ 4.4.4 với vector, deque và danh sách. Bạn có thể cần quá tải thêm void Destroy (C < T1 *, T2 > & c) cho các thùng chứa khác và/hoặc các triển khai STL khác.

+0

Điều này không xử lý trường hợp tiêu chuẩn :: some_container . Vì, some_container thường được sử dụng hơn some_container , tốt hơn là xử lý trường hợp char *. – Jagannath

1

Theo đề xuất của Tomek, chúng tôi có thể có giải pháp tương tự để xử lý việc xóa. Một cấu trúc sẽ tốt hơn một hàm miễn phí.

struct Delete 
{ 
    public: 
     template<typename T> 
     void operator()(const T* ptr) const 
     { 
      delete ptr; 
     } 
     void operator()(const char* ptr) const 
     { 
      delete[] ptr; 

    } 
}; 

for_each (some_container.begin(), some_container.end(), Delete());

+0

Tại sao điều này tốt hơn một chức năng miễn phí? –

Các vấn đề liên quan