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

std::stack::emplace

#include <stack>

template <class... Args>
void emplace(Args&&... args);

Xây dựng (construct) một phần tử mới trực tiếp tại đỉnh của std::stack, tránh việc sao chép hoặc di chuyển không cần thiết.

Tham số

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 std::stack.

Giá trị trả về

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

Đặc điểm

  1. Xây dựng phần tử tại chỗ (In-place construction): emplace() tạo phần tử mới trực tiếp trong bộ nhớ của underlying container tại vị trí đỉnh stack, 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.
  2. Tránh sao chép và di chuyển: 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.
  3. Hỗ trợ variadic template: 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ử.
  4. Dựa trên underlying container: emplace() của std::stack thực chất gọi hàm emplace_back() (đối với std::deque, std::list) hoặc emplace_back() (đối với std::vector) của underlying container.
  5. Phân biệt với push(): push() 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 std::stack, cho phép dùng emplace() ngay cả khi kiểu phần tử không hỗ trợ copy/move constructor.
  6. Có thể ném ngoại lệ: Nếu việc cấp phát bộ nhớ cho phần tử mới thất bại, emplace() có thể ném ra ngoại lệ std::bad_alloc. Ngoài ra, nếu constructor của value_type ném ngoại lệ, emplace cũng sẽ ném ngoại lệ.
  7. Độ phức tạp: Độ phức tạp của emplace()O(1) - thời gian hằng số (amortized), giống như push().

Ví dụ

#include <iostream>
#include <stack>
#include <string>

int main() {
std::stack<std::pair<int, std::string>> mystack;

// Thêm một phần tử mới vào đỉnh stack, sử dụng emplace()
mystack.emplace(10, "Hello");

// Thêm một phần tử mới vào đỉnh stack, sử dụng emplace()
mystack.emplace(20, "World");

// In ra phần tử trên cùng của stack
std::cout << "Top element: (" << mystack.top().first << ", " << mystack.top().second << ")\n";
// Output: Top element: (20, World)

return 0;
}

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

#include <iostream>
#include <stack>

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::stack<NonCopyable> mystack;

// mystack.push(NonCopyable(10)); // Error: Copy constructor is deleted

mystack.emplace(10); // OK: Constructs the element in-place
mystack.emplace(20); // OK: Constructs the element in-place

std::cout << "Top element data: " << mystack.top().data << '\n'; // Output: Top element data: 20

return 0;
}

Các hàm liên quan

pushThêm một phần tử mới vào đỉnh của std::stack
popXóa phần tử ở đỉnh của std::stack