Chuyển tới nội dung chính

std::list::splice

#include <list>

// Phiên bản 1: Chuyển toàn bộ list other
void splice(const_iterator pos, list& other);
void splice(const_iterator pos, list&& other); // (since C++11)

// Phiên bản 2: Chuyển một phần tử đơn lẻ
void splice(const_iterator pos, list& other, const_iterator it);
void splice(const_iterator pos, list&& other, const_iterator it); // (since C++11)

// Phiên bản 3: Chuyển một phạm vi các phần tử
void splice(const_iterator pos, list& other, const_iterator first, const_iterator last);
void splice(const_iterator pos, list&& other, const_iterator first, const_iterator last); // (since C++11)

Chuyển (transfer) các phần tử từ một std::list khác sang std::list hiện tại, tại một vị trí xác định.

Tham số

pos

  • const_iterator trỏ đến vị trí mà tại đó các phần tử sẽ được chèn vào trước pos. pos phải là một iterator hợp lệ trong std::list hiện tại.

other

  • std::list khác chứa các phần tử cần chuyển. other có thể là chính std::list hiện tại (trong trường hợp phiên bản 2 và 3).

it

  • const_iterator trỏ đến phần tử duy nhất cần chuyển từ other (phiên bản 2). it phải là một iterator hợp lệ trong other.

first, last

  • const_iterator xác định phạm vi các phần tử cần chuyển từ other (phiên bản 3). first phải trỏ đến phần tử đầu tiên cần chuyển, last trỏ đến phần tử sau phần tử cuối cùng cần chuyển (past-the-end).

Giá trị trả về

Không có giá trị trả về

Đặc điểm

  1. Chuyển phần tử, không sao chép: splice() chuyển các phần tử từ std::list nguồn sang std::list đích, không tạo ra các bản sao. Do đó, thao tác này rất hiệu quả.
  2. other trở thành rỗng (phiên bản 1): Khi chuyển toàn bộ std::list other, other sẽ trở thành rỗng sau khi gọi splice().
  3. Có thể làm thay đổi iterator: Việc chuyển các phần tử có thể làm thay đổi (invalidate) các iterator đang trỏ đến các phần tử trong cả hai std::list. Ngoại trừ iterator pos vẫn giữ nguyên vị trí.
  4. Trường hợp đặc biệt:
    • pos không được trỏ đến các phần tử trong phạm vi [first, last) trong phiên bản 3.
    • other không được phép bằng với std::list hiện tại trong phiên bản 1.
    • Nếu pos không hợp lệ, it không hợp lệ trong other, hoặc first, last không xác định một phạm vi hợp lệ trong other, hành vi là không xác định.
  5. noexcept: Phiên bản move splice() được đánh dấu là noexcept (kể từ C++11), nghĩa là nó được đảm bảo không ném ra ngoại lệ nào. Các phiên bản copy thì có thể ném ngoại lệ nếu constructor, copy constructor hoặc destructor của phần tử được chèn ném ngoại lệ.
  6. Hiệu quả: splice() thường được thực hiện với độ phức tạp rất tốt:
    • Phiên bản 1 (chuyển toàn bộ): O(1).
    • Phiên bản 2 (chuyển một phần tử): O(1).
    • Phiên bản 3 (chuyển một phạm vi): O(n), với n là số phần tử được chuyển.

Ví dụ

#include <iostream>
#include <list>

int main() {
std::list<int> list1 = {1, 2, 3};
std::list<int> list2 = {4, 5, 6};

// Phiên bản 1: Chuyển toàn bộ list2 vào đầu list1
list1.splice(list1.begin(), list2);
std::cout << "list1 after splice(list1.begin(), list2):";
for (int x : list1) std::cout << ' ' << x; // Output: list1 after splice(list1.begin(), list2): 4 5 6 1 2 3
std::cout << '\n';
std::cout << "list2 after splice(list1.begin(), list2):";
for (int x : list2) std::cout << ' ' << x; // Output: list2 after splice(list1.begin(), list2): (empty)
std::cout << '\n';

list2 = {7,8,9};
// Phiên bản 2: Chuyển phần tử thứ hai của list2 vào cuối list1
auto it = ++++list2.begin(); // it trỏ đến phần tử 8
list1.splice(list1.end(), list2, it);
std::cout << "list1 after splice(list1.end(), list2, it):";
for (int x : list1) std::cout << ' ' << x; // Output: list1 after splice(list1.end(), list2, it): 4 5 6 1 2 3 8
std::cout << '\n';
std::cout << "list2 after splice(list1.end(), list2, it):";
for (int x : list2) std::cout << ' ' << x; // Output: list2 after splice(list1.end(), list2, it): 7 9
std::cout << '\n';

// Phiên bản 3: Chuyển hai phần tử đầu của list2 vào giữa list1
list1.splice(++++list1.begin(), list2, list2.begin(), ++++list2.begin());
std::cout << "list1 after splice(++++list1.begin(), list2, list2.begin(), ++++list2.begin()):";
for (int x : list1) std::cout << ' ' << x; // Output: list1 after splice(++++list1.begin(), list2, list2.begin(), ++++list2.begin()): 4 5 7 9 6 1 2 3 8
std::cout << '\n';
std::cout << "list2 after splice(++++list1.begin(), list2, list2.begin(), ++++list2.begin()):";
for (int x : list2) std::cout << ' ' << x; // Output: list2 after splice(++++list1.begin(), list2, list2.begin(), ++++list2.begin()): (empty)
std::cout << '\n';
return 0;
}

Các hàm liên quan

insertChèn một hoặc nhiều phần tử mới vào một vị trí cụ thể trong std::list
mergeHợp nhất (merge) hai std::list đã được sắp xếp thành một std::list duy nhất
eraseXóa một hoặc nhiều phần tử khỏi std::list tại một vị trí cụ thể hoặc trong một phạm vi