2012-04-03 35 views
6

Tôi muốn biết tôi có cần viết hàm hủy trong lớp khi không sử dụng con trỏ thô nữa không? Chỉ cần tăng con trỏ thông minh.Con trỏ & phá hủy thông minh

+0

lẽ @simchona biết một cái gì đó tôi không, nhưng con trỏ thông minh không làm giảm bớt nhu cầu dọn dẹp, họ chỉ cần thay đổi như thế nào (khi nào) nó sẽ xảy ra. –

+2

Tôi đang đọc câu hỏi này, làm tăng các con trỏ thông minh vào và xóa bỏ sự cần thiết phải viết các trình phá hủy trong nhiều trường hợp? Đúng không? – gymbrall

+0

@Yeah, nếu bạn có một deep_pointer (hoặc bất cứ điều gì nó được gọi là), thì bạn không cần gán/di chuyển/destructor/constructors. (Mặc dù các nhà xây dựng đôi khi vẫn có thể tiện dụng) –

Trả lời

-2

Bạn nên luôn cân nhắc việc cung cấp trình phá hủy. Bạn sẽ sử dụng nó để giải phóng bất kỳ tài nguyên nào mà lớp của bạn đang nắm giữ. Thường thì các lớp hủy lớp smart_ptr của tôi trống rỗng nhưng không phải lúc nào cũng vậy. Các luồng tệp, kết nối cơ sở dữ liệu, v.v. tất cả đều cần dọn dẹp thích hợp.

+0

Tất cả những thứ đó có thể được làm sạch bằng cách gói chúng trong một lớp RAII, giống như một 'smart_ptr'. Với C++ 11, class destructors sẽ rất hiếm. –

+1

@Mooing Không đùa đâu. Con trỏ thông minh/RAII giảm mã của tôi rất nhiều và các trình phá hoại của tôi thường trống. Họ mất một thời gian để làm quen, nhưng họ đáng được học hỏi chắc chắn. – Aura

10

Tăng con trỏ thông minh bằng chính mình không có liên quan gì đến nhu cầu phá hủy. Tất cả những gì họ làm là loại bỏ sự cần thiết cho bạn để gọi xóa trên bộ nhớ được cấp phát mà họ đang quản lý hiệu quả. Do đó, nếu trước đó bạn bắt đầu sử dụng con trỏ thông minh, tất cả những gì bạn có trong trình phá hủy là gọi để xóa và xóa [] giải phóng bộ nhớ của các thành viên lớp được phân bổ động và bây giờ bạn đã chuyển tất cả các con trỏ thông thường sang con trỏ thông minh, bạn có thể có lẽ chỉ cần chuyển sang một destructor trống như bây giờ họ sẽ làm sạch cho mình khi họ đi ra khỏi phạm vi.

Tuy nhiên, nếu vì lý do gì, bạn có một lớp học cần dọn dẹp (dọn dẹp tệp, ổ cắm, tài nguyên khác, v.v.), bạn vẫn sẽ cần phải cung cấp một destructor để làm điều đó.

Hãy cho tôi biết nếu điều đó có ích.

+0

Tất cả những thứ đó có thể được làm sạch bằng cách gói chúng trong một lớp RAII, giống như một 'smart_ptr'. Với C++ 11, class destructors sẽ rất hiếm. –

4

Mỗi loại tài nguyên phải có một lớp RAII để quản lý tài nguyên đó. Nếu bạn cũng có một con trỏ thông minh với ngữ nghĩa bản sao sâu (khá dễ làm), đó là tất cả những gì bạn cần để quản lý tài nguyên của bạn 99,9% thời gian. Tôi không biết tại sao unique_ptr không làm bản sao sâu, cũng như không có con trỏ thông minh nào, nhưng nếu bạn có hai thứ đó, bạn không cần viết các hàm tạo bản sao, di chuyển các hàm tạo, toán tử gán, di chuyển các toán tử gán cũng như các hàm hủy. Bạn có thể hoặc có thể không phải cung cấp các nhà xây dựng khác (bao gồm cả nhà xây dựng mặc định), nhưng đó là năm nơi ít hơn để phạm sai lầm.

#include <memory> 

template<class Type, class Del = std::default_delete<Type> > 
class deep_ptr : public std::unique_ptr<Type, Del> { 
public: 
    typedef std::unique_ptr<Type, Del> base; 
    typedef typename base::element_type element_type; 
    typedef typename base::deleter_type deleter_type; 
    typedef typename base::pointer pointer; 

    deep_ptr() : base() {} 
    //deep_ptr(std::nullptr_t p) : base(p) {} //GCC no has nullptr_t? 
    explicit deep_ptr(pointer p) : base() {} 
    deep_ptr(pointer p, const typename std::remove_reference<Del>::type &d) : base(p, d) {} //I faked this, it isn't quite right 
    deep_ptr(pointer p, typename std::remove_reference<Del>::type&& d): base(p, d) {} 
    deep_ptr(const deep_ptr& rhs) : base(new Type(*rhs)) {} 
    template<class Type2, class Del2> 
    deep_ptr(const deep_ptr<Type2, Del2>& rhs) : base(new Type(*rhs)) {} 
    deep_ptr(deep_ptr&& rhs) : base(std::move(rhs)) {} 
    template<class Type2, class Del2> 
    deep_ptr(deep_ptr<Type2, Del2>&& rhs) : base(std::move(rhs)) {} 

    deep_ptr& operator=(const deep_ptr& rhs) {base::reset(new Type(*rhs)); return *this;} 
    template<class Type2, class Del2> 
    deep_ptr& operator=(const deep_ptr<Type2, Del2>& rhs) {base::reset(new Type(*rhs)); return *this;} 
    deep_ptr& operator=(deep_ptr&& rhs) {base::reset(rhs.release()); return *this;} 
    template<class Type2, class Del2> 
    deep_ptr& operator=(deep_ptr<Type2, Del2>&& rhs) {base::reset(rhs.release()); return *this;} 
    void swap(deep_ptr& rhs) {base::swap(rhs.ptr);} 
    friend void swap(deep_ptr& lhs, deep_ptr& rhs) {lhs.swap(rhs.ptr);} 
}; 

Với lớp này (hoặc tương tự), bạn không cần gì nhiều!

struct dog { 
    deep_ptr<std::string> name; 
}; 

int main() { 
    dog first; //default construct a dog 
    first.name.reset(new std::string("Fred")); 
    dog second(first); //copy construct a dog 
    std::cout << *first.name << ' ' << *second.name << '\n'; 
    second.name->at(3) = 'o'; 
    std::cout << *first.name << ' ' << *second.name << '\n'; 
    second = first; //assign a dog 
    std::cout << *first.name << ' ' << *second.name << '\n'; 
} 

Như đã trình bày ở http://ideone.com/Kdhj8

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