2009-12-07 18 views
19

Tôi chỉ đọc số này article và muốn lời khuyên của SO folks:Có nên gọi "xóa mục này" trong phương thức thành viên không?

Q: Nên delete this; được gọi từ trong một phương pháp thành viên?

+7

Câu hỏi hay hơn "Bạn có bao giờ sử dụng 'xóa nội dung này'" không? Trả lời - không. –

+13

Có những trường hợp hiếm hoi khi thích hợp để gọi "xóa mục này" - nhưng chúng rất hiếm ... –

+2

@Neil: Bạn không thể sử dụng 'xóa mục này' ở bất kỳ đâu ngoài chức năng thành viên (hoặc bộ khởi tạo trong hàm tạo Tôi đoán, nhưng điều đó chỉ làm tổn thương não của tôi). Vì vậy, bạn hoàn toàn nên đăng bài đó như một câu trả lời. –

Trả lời

33

Thông thường đây là một ý tưởng tồi, nhưng nó đôi khi hữu ích.

Hoàn toàn an toàn miễn là bạn không sử dụng bất kỳ biến thành viên nào sau khi xóa và miễn là khách hàng gọi phương thức này hiểu nó có thể xóa đối tượng.

Một ví dụ tốt về khi điều này rất hữu ích là nếu lớp học của bạn sử dụng tài liệu tham khảo đếm:

void Ref() { 
    m_References++; 
} 

void Deref() { 
    m_References--; 
    if (m_References == 0) { 
    delete this; 
    } 
} 
+3

làm thế nào để bạn đánh vần "con trỏ lơ lửng"? – elcuco

+16

Bạn chỉ cần viết nó là tốt, Elcuco. Ý bạn là sao? Bạn có sợ rằng một đối tượng phá hủy chính nó sẽ tạo ra nhiều con trỏ lủng lẳng hơn nếu có cái gì đó khác phá hủy đối tượng thay vào đó? 'foo-> Deref()' không tệ hơn 'if (foo-> Deref() == 0) xóa foo;'. Bên cạnh đó, nếu số tham chiếu bằng không, thì không còn bất kỳ con trỏ nào khác bị treo lơ lửng. –

1

Không có lý do chính đáng nào để làm như vậy.

Vấn đề là khi bạn gọi delete this trong chức năng thành viên, bạn đang tạo ra một hiệu ứng phụ khó chịu - người gọi vẫn có tham chiếu đến cá thể của bạn hiện đã hoàn toàn không hợp lệ.

Đây có lẽ không phải là hành vi mong đợi, vì vậy nó có thể dễ dàng dẫn đến các lỗi khó chịu. Điều đó đang được nói, có những lúc điều này là thích hợp (tôi đã thấy một số lược đồ quản lý bộ nhớ, với một số thư viện, nơi bạn tạo một cách rõ ràng các phương thức trong các lớp tự xóa - chủ yếu cho khả năng tương tác ngôn ngữ). Nói chung, tôi nghĩ rằng đó là thực tế xấu, mặc dù.

12

Tôi nghĩ có thực sự 2 câu hỏi ở đây

thể xóa này được hợp lệ gọi từ một phương pháp thành viên ?

Có. Điều này là hợp pháp miễn là bạn rất cẩn thận với việc sử dụng.

Có nên xóa mục này trong phương thức thành viên không?

Trong trường hợp rất cụ thể, điều này là cần thiết. Ví dụ, một số loại con trỏ thông minh nhất định sử dụng mẫu delete this để tiêu diệt con trỏ. Ví dụ: CComPtr<> kiểu.

Ngoài con trỏ thông minh, bạn nên tránh trừ khi bạn có lý do chính đáng để thực hiện việc này. Thậm chí sau đó, tôi sẽ cẩn thận xem xét lại kịch bản của tôi và xem nếu có một cách xung quanh nó.

5

Có, có một vài trường hợp thông thường.

đếm tham khảo:

void release() 
{ 
    cnt--; 
    if (cnt == 0) 
    delete this; 
} 

GUI lập trình. Trong một số khung công tác, khi người dùng đóng cửa sổ, cửa sổ sẽ tự xóa.

11

Có bạn có thể và here's một lời giải thích về thời gian và lý do tại sao

+1

Hoặc đây là một liên kết giải thích sự nguy hiểm và đọc giữa các dòng lý do tại sao bạn không nên làm điều đó. –

0

Bạn có thể làm điều đó, với điều kiện các yếu tố cuối cùng của nó trong một hàm thành viên, và sau khi trở về bạn quên rằng đối tượng đã từng tồn tại .... nhưng vâng, như bài viết đó hỏi ... Tại sao bạn muốn làm điều này?Tôi không biết tiêu chuẩn nói gì, nhưng nó mang đến cho tôi một cảm giác vui nhộn: P

Tôi đoán điều này giống như bạn từng sử dụng câu lệnh GOTO và cá nhân tôi sử dụng GOTO để xóa tài nguyên trong C đôi khi, đặc biệt là trong điều kiện đặc biệt.

Tôi tự hỏi những gì ý nghĩa nhà nước chia sẻ là (mờ tuyên bố tôi biết): P

1

Một số thư viện luồng sử dụng nó khi thực hiện một ô tô phá hủy về việc chấm dứt chủ đề.

void Thread::threadFunc() 
{ 
    doRun(); 

    if(this->destroyOnExit == true) 
     delete this; 
} 
1

Điều này thường được sử dụng trong các ngày MFC. IIRC tin nhắn cuối cùng mà cửa sổ nhận được là WM_NCDESTROY, tại thời điểm đó bạn có thể gọi delete this, giả sử bạn là một hình thức buồn bã dĩ nhiên (mặc dù bản thân MFC đã làm điều này vào những thời điểm tôi nghĩ.)

+1

Có, chức năng MFC OnDestroy() làm điều đó :) –

5

Sẵn sàng cho phiếu bầu.

nên nó: Số
Can nó Về mặt kỹ thuật: Có
có phải là một ý tưởng tốt: Tuyệt đối không.
Có tình huống nào hữu ích: Tất nhiên. Nếu bạn là C++ foo là cực kỳ mạnh mẽ. Nhưng hầu hết mọi người không tốt. Vì vậy, chỉ làm điều này nếu bạn có một đội ngũ những người làm việc với bạn có thể làm xem xét mã phong nha.

Tại sao:
Không có cách nào cho một đối tượng khi biết rằng nó đã được cấp phát động (và do đó cần xóa) hoặc là một đối tượng bình thường (và do đó phải không bị xóa) và do đó làm thế nào mà nó decidide thời tiết cần xóa. Vì vậy, nếu một đối tượng đang xóa chính nó thì theo ý kiến ​​của tôi thì có một điều gì đó rất sai với thiết kế.

Nếu bạn có đối tượng cần quản lý thì bạn nên viết đối tượng seprate để thực hiện việc quản lý (do đó con trỏ thông minh). Hãy để đối tượng làm những gì nó là tốt tại, sau đó seporate việc quản lý của đối tượng vào đối tượng khác.

+0

Cũng lưu ý rằng "bên ngoài lớp" bạn vẫn không thể chắc chắn rằng con trỏ thực sự trỏ đến đối tượng được cấp động và không phải là đối tượng tự động hoặc tĩnh chẳng hạn. (Trong thực tế, tôi nghĩ rằng trong nhiều trường hợp bạn có thể thậm chí còn ít chắc chắn hơn trong chức năng thành viên ...) Vì vậy, 'xóa p' là nguy hiểm bất kể' p' là 'this' hay không. –

+0

@Adam: Cảm ơn. Nhưng như đã chỉ ra nó 'có thể' có ích. Nhưng trong C++ hiện đại nó được coi là thực hành tốt hơn để quản lý riêng biệt của đối tượng từ việc thực hiện các đối tượng (Do đó con trỏ thông minh đang được sử dụng chứ không phải là COM). Cũng lưu ý rằng một đối tượng quản lý có thể dễ dàng được cấp phép rằng đối tượng mà nó quản lý được phân bổ động để hoàn toàn là tiền đề giả. –

0

Có. Giống như tất cả các câu trả lời, nếu bạn chắc chắn 100% rằng dữ liệu của lớp học sẽ không được sử dụng sau khi gọi delete this.

Ví dụ, trong một dự án:

void Test() 
MyClass * Someclass = new MyClass; 
SomeClass->DoYourThing(); 
SomeClass->KillYourself(); 
return; 

void MyClass::DoYourThing() { return; } 
void MyClass::KillYourself() {delete this;} 

Rất đơn giản giải thích, dự án sử dụng delete this; như một phần của công tác quản lý bộ nhớ cho các đối tượng của loại hình đó; nhà xây dựng của họ đã thêm họ vào danh sách riêng tư của các lớp thuộc loại đó đang được sử dụng và xóa chính họ khỏi danh sách đó khi họ bị phá hủy và sau đó xóa chính họ (điều này không có trong một destructor). Bất kỳ đối tượng của lớp đó đã không bị xóa mình khi chương trình đạt điểm cuối của nó thì tất cả đã KillYourself() tương đương của họ gọi từ một hàm thành viên tĩnh CleanYourselves()

0
  1. delete this không thể được gọi từ một hàm thành viên không :)
  2. Đó là một ý tưởng tồi để làm cho đến khi bạn hiểu được hậu quả của nó.
0

Mặc dù không liên quan trực tiếp đến chủ đề này tôi muốn làm rõ điều này. Tôi đã được hỏi một câu hỏi đưa ra một tình huống:

int* a = new int ; 
int* b = a ; 
delete a; 

Bây giờ là tuyên bố tiếp theo an toàn?

cout<<*b ;

câu trả lời của tôi: Sau khi xóa một, vị trí được trỏ đến bởi một đã được đánh dấu để xóa và tại bất kỳ thời điểm nó có thể được gán cho một số đối tượng khác. Do đó việc truy cập giá trị bằng cách sử dụng b không an toàn vì nó có thể bị sửa đổi sau khi được cấp phát cho một số đối tượng khác.

Lưu ý: Không có yêu cầu giảm giá, đây chỉ là cách làm rõ

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