2012-07-25 25 views
5

Tôi có một lớp templated, myFoo, lưu trữ "thứ" của loại T, có thể là nguyên thủy hoặc con trỏ đến các kiểu phức tạp. Khi myFoo bị xóa, tôi muốn giải phóng tất cả bộ nhớ liên quan đến mọi thứ nó xảy ra để lưu trữ. Điều này có nghĩa là tôi cần phải gọi xóa trên mỗi con trỏ được lưu trữ nhưng tôi cũng có thể kết thúc gọi xóa trên một nguyên thủy. Cái này có an toàn không ??Tôi có thể gọi xóa trên tài liệu gốc không?

Tôi đã bao gồm một bản phác thảo của myFoo bên dưới để làm nổi bật những gì đang diễn ra tốt hơn. Tôi không chắc chắn nếu hành vi của destructor được xác định rõ.

template<class T> 
class myFoo 
{ 
    public: 
     myFoo(int size) 
     { 
      size_ = size; 
      T* foo = new T[size_]; 
     } 

     void addFoo(T tmp, int index) 
     { 
      foo[index] = tmp; 
     } 

     virtual ~myFoo() 
     { 
      for(int i=0; i < size_; i++) 
      { 
       delete foo[i]; 
      } 
      delete [] foo; 
     } 

    private: 
     int size_; 
     T* foo; 
} 
+0

Bạn không thể chuyên cho con trỏ? – chris

+1

Như được viết, mã của bạn không có ý nghĩa đối với * bất kỳ * loại 'T', ít nhất là ngữ nghĩa: Bạn đang trộn lẫn trách nhiệm quyền sở hữu và lớp học sẽ là một cơn ác mộng khả năng sử dụng, dễ đọc và bảo trì. Trong ngắn hạn, nó không nên được * của bạn * quan tâm những gì 'T' là, và khách hàng nên làm sạch của riêng mình lên (hoặc tất nhiên sử dụng một con trỏ thông minh). –

+0

@KerrekSB: Tôi đang viết một cơ sở dữ liệu các loại. Tôi muốn chèn dữ liệu vào đó. Nó có ý nghĩa cho cơ sở dữ liệu để sở hữu bộ nhớ của những thứ tôi đang lưu trữ bên trong nó. Nếu không, tôi cần phải quản lý tất cả dữ liệu từ cơ sở dữ liệu bên ngoài. Đó là một chút "wtf ??" nếu tôi làm như bạn đề nghị. – Daniel

Trả lời

5

Điều duy nhất bạn có thể gọi delete là loại con trỏ. Đó là lỗi khi gọi số delete trên số điện thoại int. Nếu bạn sắp xếp các mẫu của bạn để mã của bạn cố gắng làm điều gì đó sai sót, trình biên dịch sẽ cho bạn biết và từ chối biên dịch mã của bạn.

Vì vậy, không, bạn không phải lo lắng về việc "vô tình" xóa một con trỏ không.

+0

Vậy làm thế nào tôi có thể đạt được hành vi mà tôi mô tả? – Daniel

+0

Bạn có thể có các mẫu khác nhau tùy thuộc vào việc bạn muốn lưu trữ con trỏ hay không. Hoặc, bạn có thể lưu trữ các cá thể của một lớp con trỏ thông minh và dựa vào hàm hủy của con trỏ thông minh để thực hiện việc xóa. –

+0

Cảm ơn Greg. Tôi nghĩ rằng bạn (và những người khác) đã thuyết phục tôi rằng con trỏ thông minh là con đường để đi. – Daniel

1

Template chuyên môn

template <class T> struct delete_it; 

template <class T> struct delete_it<T*> 
{ 
    static void func(T* ptr) { delete ptr; } 
}; 

template <> struct delete_it<int> 
{ 
    static void func(int) {} 
}; 

template <> struct delete_it<double> 
{ 
    static void func(double) {} 
}; 

Lặp lại cho tất cả các loại nguyên thủy. Sau đó,

virtual ~myFoo() 
    { 
     for(int i=0; i < size_; i++) 
     { 
      delete_it<T>::func(foo[i]); 
     } 
     delete [] foo; 
    } 

Mã không được kiểm tra.