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

Triển khai Copy Constructor trong C++

Copy Constructor là constructor đặc biệt tạo đối tượng mới bằng cách sao chép từ đối tượng cùng lớp đã tồn tại. Được gọi khi:

  • Khởi tạo đối tượng từ đối tượng khác: Class b = a;
  • Truyền đối tượng vào hàm theo giá trị: func(obj)
  • Trả về đối tượng từ hàm theo giá trị: return obj;

Cú pháp chuẩn


ClassName(const ClassName& other) {
    // Sao chép dữ liệu từ other
}

Khi nào CẦN tự viết Copy Constructor?

  • Lớp có con trỏ quản lý bộ nhớ động
  • Lớp có tài nguyên cần deep copy (file handle, socket, GPU resource...)
  • Cần logic sao chép tùy chỉnh

Nếu không tự viết, compiler tạo default copy constructor (shallow copy - sao chép bit-by-bit).

Ví dụ: Deep Copy cho class có con trỏ

#include <iostream>

using namespace std;

class Line {
public:
    int getLength() const { return *ptr; }
    
    Line(int len) {           // Constructor thường
        cout << "Constructor thuong cap phat ptr" << endl;
        ptr = new int;
        *ptr = len;
    }
    
    Line(const Line& obj) {   // Copy Constructor - DEEP COPY
        cout << "Copy constructor cap phat ptr." << endl;
        ptr = new int;
        *ptr = *obj.ptr;      // Sao chép GIÁ TRỊ, không sao chép con trỏ
    }
    
    ~Line() {                 // Destructor
        cout << "Giai phong bo nho!" << endl;
        delete ptr;
    }
    
private:
    int* ptr;
};

void display(Line obj) {  // Truyền theo giá trị -> gọi copy constructor
    cout << "Do dai: " << obj.getLength() << endl;
}

int main() {
    Line line(10);
    display(line);  // Tạo bản sao, gọi copy constructor
    return 0;
}

Kết quả

Constructor thuong cap phat ptr
Copy constructor cap phat ptr.
Do dai: 10
Giai phong bo nho!
Giai phong bo nho!

Ví dụ 2: Tạo đối tượng mới từ đối tượng hiện có


int main() {
    Line line1(10);
    Line line2 = line1;  // Gọi copy constructor
    
    display(line1);
    display(line2);
    return 0;
}

Kết quả

Constructor thuong cap phat ptr
Copy constructor cap phat ptr.
Copy constructor cap phat ptr.
Do dai: 10
Giai phong bo nho!
Copy constructor cap phat ptr.
Do dai: 10
Giai phong bo nho!
Giai phong bo nho!
Giai phong bo nho!

Shallow Copy vs Deep Copy

LoạiHành viVấn đề
Shallow (Default)Copy giá trị con trỏDouble free, dangling pointer
Deep (Tự viết)Cấp phát mới, copy dữ liệuAn toàn, độc lập

Rule of Three / Five / Zero

  • Rule of Three (C++98): Nếu cần 1 trong 3: destructor, copy constructor, copy assignment → cần cả 3
  • Rule of Five (C++11): + move constructor, move assignment
  • Rule of Zero: Dùng RAII (vector, unique_ptr, shared_ptr) → không cần viết gì

C++11: Move Constructor


Line(Line&& other) noexcept : ptr(other.ptr) {
    other.ptr = nullptr;  // Chuyển quyền sở hữu
}

Khuyến nghị hiện đại

Tránh quản lý bộ nhớ thủ công. Dùng std::vector, std::string, std::unique_ptr → Compiler tự tạo đúng copy/move constructor.