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

Các phương thức sao chép trong C++ STL - std::copy(), copy_n(), copy_if(), copy_backward()


Như tên phương thức cho thấy, copy() được dùng để sao chép dữ liệu qua nhiều phương thức khác nhau có sẵn trong C++ STL. Tất cả các phương thức khác nhau về chức năng và tham số. Các phương thức này nằm trong header <algorithm>. Hãy thảo luận chi tiết từng phương thức và chức năng của chúng.

copy(start_i1, end_i1, start_i2)

Phương thức này sao chép dữ liệu từ iterator này sang iterator khác trong phạm vi xác định, trong đó cả phần tử bắt đầu và kết thúc đều được bao gồm (inclusive). Nó nhận 3 đối số:

  • Start_i1 – Trỏ đến phần tử đầu tiên của iterator nguồn (i_1) từ nơi các phần tử sẽ được sao chép sang iterator đích (i_2).
  • End_i1 – Trỏ đến phần tử cuối cùng của iterator nguồn (i_1) đến nơi các phần tử sẽ được sao chép sang iterator đích (i_2).
  • Start_i2 – Trỏ đến vị trí ban đầu của iterator đích (i_2) nơi các phần tử sẽ được sao chép đến.

Giá trị trả về – Trả về iterator trỏ đến cuối iterator đích (i_2) nơi các phần tử đã được sao chép.

Ví dụ

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
    // Tạo vector v1
    vector<int> vec_1 = { 10, 20, 30, 40, 50 };
    // Khai báo vector rỗng kích thước 6
    vector<int> vec_2(6);
    // Sử dụng copy() để sao chép vào vector 2
    copy(vec_1.begin(), vec_1.begin() + 4, vec_2.begin());
    // In vector mới
    cout << "Các phần tử trong v2 sao chép từ v1: ";
    for (int i = 0; i < 4; i++) {
        cout << vec_2[i] << " ";
    }
    return 0;
}

Kết quả

Các phần tử trong v2 sao chép từ v1: 10 20 30 40

copy_n(start_i1, total, start_i2)

Phương thức này cũng sao chép dữ liệu từ iterator này sang iterator khác nhưng chỉ định tổng số phần tử cần sao chép bắt đầu từ vị trí cho trước. Nó nhận 3 đối số:

  • Start_i1 – Trỏ đến phần tử đầu tiên của iterator nguồn (i_1).
  • Total – Số lượng phần tử sẽ được sao chép bắt đầu từ vị trí start_i1. Có thể nhận giá trị dương hoặc âm, nhưng không thực hiện thao tác nào nếu là giá trị âm.
  • Start_i2 – Trỏ đến vị trí ban đầu của iterator đích (i_2).

Giá trị trả về – Trả về iterator trỏ đến cuối iterator đích (i_2) nơi các phần tử đã được sao chép.

Ví dụ

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
    vector<int> vec_1 = { 10, 20, 30, 40, 50 };
    vector<int> vec_2(6);
    // Sử dụng copy_n() để sao chép 4 phần tử
    copy_n(vec_1.begin(), 4, vec_2.begin());
    cout << "Các phần tử trong v2 sao chép từ v1: ";
    for (int i = 0; i < 4; i++) {
        cout << vec_2[i] << " ";
    }
    return 0;
}

Kết quả

Các phần tử trong v2 sao chép từ v1: 10 20 30 40

copy_if(start_i1, end_i1, start_i2, Boolean function)

Phương thức này sao chép dữ liệu từ iterator nguồn sang iterator đích trong phạm vi xác định dựa trên điều kiện được định nghĩa trong đối số thứ 4 (hàm Boolean). Nó nhận 4 đối số:

  • Start_i1 – Iterator nguồn bắt đầu.
  • End_i1 – Iterator nguồn kết thúc.
  • Start_i2 – Iterator đích bắt đầu.
  • Boolean function – Hàm điều kiện trả về true/false. Chỉ các phần tử thỏa mãn điều kiện (trả về true) mới được sao chép.

Giá trị trả về – Trả về iterator trỏ đến cuối iterator đích.

Ví dụ

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
    vector<int> vec_1 = { 10, 21, 30, 40, 57 };
    vector<int> vec_2(6);
    // Sao chép các số chẵn từ vec_1 sang vec_2
    copy_if(vec_1.begin(), vec_1.end(), vec_2.begin(), [](int i) { return i % 2 == 0; });
    cout << "Các phần tử trong v2 sao chép từ v1: ";
    for (int i = 0; i < 4; i++) {
        cout << vec_2[i] << " ";
    }
    return 0;
}

Kết quả

Các phần tử trong v2 sao chép từ v1: 10 30 40 0

copy_backward(start_i1, end_i1, end_i2)

Phương thức này sao chép dữ liệu từ iterator nguồn sang iterator đích trong phạm vi xác định theo hướng ngược (backward). Nghĩa là iterator đích được di chuyển đến vị trí cuối dựa trên kích thước, và các phần tử được dán từ vị trí đó. Nó nhận 3 đối số:

  • Start_i1 – Iterator nguồn bắt đầu.
  • End_i1 – Iterator nguồn kết thúc.
  • end_i2 – Trỏ đến vị trí kết thúc của iterator đích (i_2) nơi các phần tử sẽ được sao chép đến.

Giá trị trả về – Trả về iterator trỏ đến phần tử đầu tiên của iterator đích nơi các phần tử đã được sao chép.

Ví dụ

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
    vector<int> vec_1 = { 10, 21, 30, 40, 57, 67 };
    vector<int> vec_2(6);
    // Sử dụng copy_backward() - lưu ý: vec_1.end()+4 vượt khỏi phạm vi, ví dụ gốc có lỗi logic
    // Ví dụ sửa đúng: copy_backward(vec_1.begin(), vec_1.begin()+4, vec_2.begin()+4);
    copy_backward(vec_1.begin(), vec_1.begin() + 4, vec_2.begin() + 4);
    cout << "Các phần tử trong v2 sao chép từ v1: ";
    for (int i = 0; i < vec_2.size(); i++) {
        cout << vec_2[i] << " ";
    }
    return 0;
}

Kết quả (với ví dụ sửa)

Các phần tử trong v2 sao chép từ v1: 0 0 10 21 30 40

Lưu ý: Ví dụ gốc có lỗi truy cập vượt khỏi phạm vi (vec_1.end()+4). Phiên bản trên đã sửa để chạy đúng.