Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Quy tắc Ba (Rule of Three) trong C++


Quy tắc Ba (Rule of Three) là một trong những quy tắc của C++ trong các quy tắc ngón tay cái (rules of thumb) để xây dựng code an toàn ngoại lệ (exception safe). Các quy tắc này quy định cách sử dụng các thành viên mặc định của lớp để thực hành không ngoại lệ.

Quy tắc Ba còn được gọi là Luật Ba Lớn (Law of Big Three) hoặc The Big Three, quy định cho lớp rằng: nếu một lớp định nghĩa bất kỳ một trong ba thành viên sau thì nó nên định nghĩa rõ ràng cả ba:

  • hàm hủy (destructor)
  • hàm tạo sao chép (copy constructor)
  • toán tử gán sao chép (copy assignment operator)

Ba thành viên này là các hàm thành viên đặc biệt của lớp. Nếu không có hàm nào được định nghĩa rõ ràng bởi lập trình viên, trình biên dịch sẽ cung cấp các phiên bản ngầm định (implicit). Nếu bất kỳ một trong ba được định nghĩa rõ ràng, điều đó có nghĩa là các phiên bản ngầm định cho hai cái còn lại không phù hợp và phải được định nghĩa lại.

Điều này xảy ra vì các hàm tạo sao chép và toán tử gán ngầm định thực hiện sao chép nông (shallow copy) các thành viên dữ liệu. Ta cần sao chép sâu (deep copy) khi lớp chứa con trỏ trỏ đến tài nguyên được cấp phát động.

Hàm hủy mặc định giải phóng các đối tượng không sử dụng. Khi không có hàm tạo sao chép được định nghĩa, hàm hủy sẽ chạy hai lần: một cho đối tượng chứa bản sao và một cho đối tượng gốc được sao chép dữ liệu. Để tránh điều này, định nghĩa rõ ràng trở nên cần thiết.

Hãy hiểu qua ví dụ nơi có hàm hủy nhưng không có hàm tạo sao chép và toán tử gán sao chép:

Ví dụ

#include <stdio.h> class Numbers{ private:    int num;    int* ptr;    public:    Numbers( int n, int* p ) //hàm tạo sao chép{       num =n ;       ptr = new int[ num ];    }    ~Numbers() //hàm hủy{       delete ptr;       ptr = NULL;    } }; int main(){    int arr[ 4 ] = { 11, 22, 33, 44 };    Numbers Num1( 4, arr );    // điều này gây vấn đề    Numbers Num2( Num1 );    return 0; }

Đầu ra

*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001f46c20 *** Aborted
  • Điều này xảy ra vì hàm hủy được gọi hai lần khi chương trình thoát khỏi phạm vi. Lần đầu xóa Num1, lần hai xóa Num2. Hàm tạo sao chép mặc định tạo bản sao của con trỏ ptr nhưng không cấp phát bộ nhớ cho nó. Vì vậy, khi Num1 bị xóa, các ptr tiếp theo gây lỗi chương trình.