Trích dẫn




Only a person who risks is truly free.


Ảnh

Ảnh

Thứ Năm, 16 tháng 4, 2015

Destructor, tưởng rõ mà vẫn chưa rõ

Như mình được học thì có 3 cách truyền tham số vào một hàm:

  1. Truyền tham trị
  2. Truyền tham chiếu (cho C++)
  3. Truyền địa chỉ (aka chuyền tham số, mà không rõ nên để địa chỉ nhé)
Hồi đầu mình học C/C++, thì mình chủ yếu dùng truyền địa chỉ và truyền tham trị. Nếu biến truyền vào hàm để thay đổi thì mình thích dùng truyền địa chỉ hơn vì nó rõ ràng. Địa chỉ là một thứ rất rõ ràng, phân biệt giữa ô nhớ này với ô nhớ kia. Truyền vào hàm sử dụng cũng đơn giản nữa. Nếu muốn dùng địa chỉ cho việc gì đó cứ để tên biến. Muốn truy xuất giá trị của ô có địa chỉ đó thì dùng phương thức dereference (đặt * trước tên biến).
Còn truyền tham chiếu? Ông này thì của C++. Cả một tháng nay toàn sài cái này. Cũng không có gì phức tạp lắm nếu truyền bình thường, y chang thằng truyền địa chỉ mà đỡ phức tạp hơn khi sử dụng. Thấy sài sướng quá nên chuyển hẳn qua tham chiếu sài. Sài cho đã mới biết là chưa đọc hướng dẫn sử dụng... (tai hại chưa)
Rồi hôm nay có làm về struct, cụ thể là làm cái destructor cho List. Oái ăm, chương trình bị lỗi, cái danh sách liên kết tự nhiên bị destruct hết, đáng lẽ sau khi thoát chương trình thì nó sẽ destruct chứ, sao đang chạy mà lại destruct. Hàm đầu tiên cho thằng List vào là hàm input(vì danh sách thay đổi nên mình cho nó truyền tham chiếu vào hàm). Sau đó mình cho nó vào hàm output(không có thay đổi gì trong danh sách nên cho truyền tham trị thôi). Ngon lành, in ra hết giá trị trong List, rồi giờ cho thằng List nhảy sang hàm khác làm, ngay khúc này bị lỗi. Cứng người, debug thì phát hiện ra sau khi thoát hàm output thì cái List cũng tự động thực hiện destructor luôn. LẠ, lên mạng tìm hiểu. Có ba thứ cần tìm hiểu:
  1. Phương thức destructor(when, how)
  2. Reference(what, how)
  3. Passing by Reference and Pointer(giống nhau và khác nhau)
Gặp những trường hợp lỗi này đúng là quý báu, lỗi 1 mà học được 10. cái thứ 3 thì cũng biết một ít thôi, 2 anh Ref và Poi này chỉ khác nhau một chút. Poi là một biến nhưng giá trị nó chứa là địa chỉ, Ref anh này chỉ là một alias (một nick name khác). Khi chúng ta gọi tên của một biến, thì chương trình sẽ tìm xem ô nhớ nào có tên như thế (tùy vào scope) -> Tức là một ô nhớ sẽ có nhiều tên, và thằng Ref sẽ là cách để ô nhớ đó có thêm một tên. không có gì ghê gớm lắm. Vậy mình dùng Pointer cũng bị lỗi này thôi.
Tìm trên mạng cũng không có gì thêm về ý 2 và 3. Vậy thì chắc là do anh destructor rồi.
Có 2 thời điểm destructor sẽ được thực hiện:
  • Khi đối tượng ra khỏi scope của nó
  • Khi ta gọi hàm hủy của đối tượng(chỉ thực sự bị hủy khi ra khỏi scope)
Nói chung là ra khỏi scope của nó thì nó sẽ gọi destructor. Ok, xem lại trưởng hợp lỗi nào, để xem scope của List ở đâu. Scope của một đối tượng là gì, đó chình là khu vực mà nó được biết đến, làm sao để biết đến, nó phải được khai báo. Ta xem lại hàm output, ta khai báo List như một tham trị (cách truyền này sẽ copy thằng List ra một bản sao khác), và tất nhiên sau khi out ra khỏi scope output thì nó sẽ hủy thằng List bản sao này, và thằng bản chính kia lại không sao. Xui thay thằng List lại chứa những địa chỉ. Thế thì khi hủy nó sẽ hủy đi các ô được cấp phát động được gọi sâu bên dưới, và thằng List bản chính chỉ giữ lại một đỉa chỉ trỏ đến một nơi hư không ~~ 
Vậy thì khi truyền tham chiếu thì như thế nào, tất nhiên scope của thằng List này sẽ nằm ở hàm main. Và khi kết thúc chương trình thì mới bị hủy theo kế hoạch.

Không có nhận xét nào:

Đăng nhận xét