Nếu một class không có con trỏ, ta không cần tự định nghĩa toán tử gán (assignment operator) hay constructor sao chép (copy constructor). Trình biên dịch C++ tự tạo chúng. Nhưng nếu các toán tử mặc định không đủ (ví dụ: class có con trỏ), ta phải tự viết.
Ví dụ vấn đề (shallow copy)
#include <iostream>
using namespace std;
class MyClass {
int *ptr;
public:
MyClass(int x = 0) { ptr = new int(x); }
void setValue(int x) { *ptr = x; }
void print() { cout << *ptr << endl; }
};
int main() {
MyClass ob1(50);
MyClass ob2;
ob2 = ob1; // shallow copy: cả hai ptr trỏ cùng địa chỉ
ob1.setValue(100); // thay đổi qua ob1
ob2.print(); // in ra 100 - lỗi logic!
}
Kết quả
100
Toán tử gán mặc định copy con trỏ (shallow copy), dẫn đến hai đối tượng chia sẻ cùng bộ nhớ. Thay đổi qua đối tượng này ảnh hưởng đến đối tượng kia.
Giải pháp: Viết toán tử gán riêng (deep copy)
#include <iostream>
using namespace std;
class MyClass {
int *ptr;
public:
MyClass(int x = 0) { ptr = new int(x); }
void setValue(int x) { *ptr = x; }
void print() { cout << *ptr << endl; }
MyClass &operator=(const MyClass &ob2) {
if (this != &ob2) { // kiểm tra tự gán
*ptr = *(ob2.ptr); // deep copy giá trị
}
return *this;
}
};
int main() {
MyClass ob1(50);
MyClass ob2;
ob2 = ob1;
ob1.setValue(100);
ob2.print(); // in ra 50 - đúng!
Kết quả
50
Toán tử gán tự viết thực hiện deep copy: cấp phát bộ nhớ riêng và copy giá trị. Luôn kiểm tra tự gán (self-assignment) để tránh lỗi.