2013-09-01 26 views
7

Tôi lo lắng về việc sử dụng loại không đầy đủ với con trỏ thông minh và cách con trỏ bị xóa. Mã sau có an toàn không? Tôi không nghĩ rằng nó sẽ được, như main.cpp sẽ tạo ra destructor mặc định của Farm mà sẽ không nhìn thấy loại hoàn chỉnh. Để làm cho nó an toàn, tôi nghĩ rằng tôi nên tạo một destructor phi nội tuyến mà nhìn thấy loại hoàn chỉnh. Đúng không?Làm cách nào để hủy lớp an toàn bằng con trỏ thông minh thành loại đối tượng không đầy đủ?

Cũng vậy, nếu tôi sử dụng std::vector<Cow> trong trang trại thay thế?

farm.h

class Cow; 

struct Farm 
{ 
    Farm(); 
    // ~Farm(); 
    std::unique_ptr<Cow> cow; 
}; 

farm.cpp

#include "cow.h" 
// cow now complete 

Farm::Farm() 
{ 
    cow.reset(new Cow); 
} 

// Farm::~Farm() {} 

main.cpp

#include "farm.h" 

int main() 
{ 
    Farm farm; 
} 

Edit: Tôi cố gắng để biên dịch với Visual Studio mà không destructor và nó nói lỗi C2338: không thể xóa loại không đầy đủ. Tôi đoán rằng câu trả lời cho câu hỏi của tôi.

+0

Lưu ý rằng với auto_ptr, mã biên dịch: -/ – Jarod42

+0

@Jarod: Có, và âm thầm làm điều sai. –

+1

http://stackoverflow.com/questions/8595471/does-the-gotw-101-solution-actually-solve-anything –

Trả lời

4

Tôi không nghĩ rằng mã của bạn nên biên dịch (và nó không trong gcc)

std::unique_ptr<Cow> sử dụng std::default_delete<Cow>, và std::default_delete<Cow>::operator() nên thất bại trong việc nhanh chóng cho một loại không đầy đủ Cow.

Xem thêm Is it true that a unique_ptr declaration, unlike a auto_ptr declaration, is well-defined when its template type is of an incomplete type?

Vì vậy, bạn nói đúng: bạn cần phải đảm bảo rằng default_delete<Cow>::operator() được khởi tạo ở đâu đó rằng loại Cow hoàn tất. Điều này có nghĩa là hàm hủy của Farm cần phải được xác định ở một nơi như vậy.

Tôi vừa nhận thấy rằng đối tượng của bạn nói "con trỏ thông minh", trong khi câu hỏi chỉ định unique_ptr. Câu trả lời sẽ khác với shared_ptr, vì std::shared_ptr<Cow>::reset() là mẫu chức năng ghi lại loại (tĩnh) của con trỏ được truyền đến nó và lưu trữ một dấu phân cách. Vì vậy, với shared_ptr tất cả những gì bạn cần là cuộc gọi đến reset có loại hoàn chỉnh Cow - vị trí của trình hủy không quan trọng.

+0

Cảm ơn. Nhưng khi nào shared_ptr cần loại hoàn chỉnh? –

+0

@NeilKirk: tại các điểm mà deleter được suy ra: - 'reset()', các hàm tạo và toán tử gán từ các kiểu con trỏ.Nếu bạn chỉ định deleter trong những trường hợp đó thì 'shared_ptr' không cần kiểu đầy đủ, chỉ có deleter tùy chỉnh của bạn. Và tất nhiên bất cứ ai sử dụng kết quả của toán tử 'operator->' và '*' ;-) –

+0

'shared_ptr' hoạt động với kiểu không đầy đủ, nhưng' unique_ptr' không – linquize

1

Trình phá hủy mặc định cho Farm sẽ bao gồm một desructor cho unique_ptr, bao gồm một destructor cho Cow. Cuộc gọi này sẽ được thực hiện ngay cả khi không có định nghĩa nào tại thời điểm biên dịch. Người liên kết sẽ được dự kiến ​​kết nối mọi thứ sau khi thực tế.

+0

Tôi đã thử nó và tôi nhận được lỗi biên dịch C2338: không thể xóa một loại không đầy đủ –

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