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

std::deque::emplace

#include <deque>

template <class... Args>
iterator emplace(const_iterator pos, Args&&... args);

Xây dựng một phần tử mới trực tiếp tại một vị trí cụ thể trong deque, tránh việc sao chép hoặc di chuyển không cần thiết.

Tham số

pos

  • Iterator trỏ đến vị trí trước vị trí cần chèn phần tử mới.
  • pos phải là một iterator hợp lệ và có thể dereference được trong deque.

args

  • Danh sách các đối số (có thể trống) được sử dụng để khởi tạo phần tử mới. Các đối số này sẽ được truyền đến constructor của kiểu phần tử value_type của deque.

Giá trị trả về

  • Trả về một iterator trỏ đến phần tử vừa mới được chèn vào.

Đặc điểm

  1. emplace() tạo một phần tử mới ngay tại vị trí được trỏ bởi iterator pos bằng cách sử dụng các đối số args để khởi tạo phần tử. Nó tương tự như insert(), nhưng thay vì nhận vào một đối tượng đã được tạo, emplace() nhận các đối số để xây dựng đối tượng ngay tại chỗ.
  2. emplace() tạo phần tử mới trực tiếp trong bộ nhớ của deque, tránh việc tạo ra các đối tượng tạm thời không cần thiết, tối ưu hiệu suất.
  3. Bằng cách xây dựng phần tử tại chỗ, emplace() giúp tránh việc sao chép (copy) hoặc di chuyển (move) các đối tượng, đặc biệt hiệu quả khi làm việc với các đối tượng lớn hoặc phức tạp.
  4. emplace() sử dụng variadic template (Args&&... args), cho phép nó nhận số lượng đối số tùy ý, phù hợp với constructor của kiểu phần tử.
  5. Việc chèn phần tử vào deque có thể làm thay đổi (invalidate) các iterator khác đang trỏ đến các phần tử trong deque.
  6. insert() sẽ tạo bản sao hoặc di chuyển phần tử được truyền vào trong khi đó emplace() sẽ xây dựng phần tử tại chỗ trong deque, cho phép dùng emplace() ngay cả khi kiểu phần tử không hỗ trợ copy/move constructor.
  7. Độ phức tạp: Độ phức tạp của emplace() tương tự như insert().
    • Chèn một phần tử: O(n) trong trường hợp xấu nhất (khi chèn vào đầu), O(1) trong trường hợp tốt nhất (khi chèn vào cuối), với n là số phần tử trong deque. Trung bình là O(min(n, N-n)) với n là khoảng cách từ pos tới đầu deque và N-n là khoảng cách từ pos đến cuối deque.

Ví dụ

#include <iostream>
#include <deque>
#include <string>

int main() {
std::deque<std::pair<int, std::string>> myDeque;

// Chèn một phần tử mới vào đầu deque, sử dụng emplace()
auto it = myDeque.emplace(myDeque.begin(), 10, "Hello");

// Chèn một phần tử mới vào sau phần tử vừa chèn, sử dụng emplace()
myDeque.emplace(it + 1, 20, "World");

// In ra các phần tử trong deque
std::cout << "myDeque:";
for (const auto& p : myDeque) {
std::cout << " (" << p.first << ", " << p.second << ")";
}
std::cout << '\n'; // Output: myDeque: (10, Hello) (20, World)

return 0;
}

Với class không hỗ trợ copy/move constructor

#include <iostream>
#include <deque>

class NonCopyable {
public:
NonCopyable(int val) : data(val) {}
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator=(const NonCopyable&) = delete;

// Move constructor/assignment are not necessary but good practice
NonCopyable(NonCopyable&&) = default;
NonCopyable& operator=(NonCopyable&&) = default;

int data;
};

int main() {
std::deque<NonCopyable> myDeque;

// myDeque.push_back(NonCopyable(10)); // Error: Copy constructor is deleted
// myDeque.insert(myDeque.begin(), NonCopyable(10)); // Error: Copy constructor is deleted

myDeque.emplace(myDeque.begin(), 10); // OK: Constructs the element in-place
myDeque.emplace(myDeque.end(), 20); // OK: Constructs the element in-place

std::cout << "myDeque:";
for (const auto& obj : myDeque) {
std::cout << " " << obj.data;
}
std::cout << '\n'; // Output: myDeque: 10 20

return 0;
}

Các hàm liên quan

emplace_frontXây dựng một phần tử mới trực tiếp tại đầu deque
emplace_backXây dựng một phần tử mới trực tiếp tại cuối deque
insertChèn một hoặc nhiều phần tử mới vào một vị trí cụ thể trong deque
eraseXóa một hoặc nhiều phần tử khỏi deque tại một vị trí cụ thể hoặc trong một phạm vi
assignGán các phần tử mới cho deque, thay thế nội dung hiện tại của nó