std::priority_queue::emplace
#include <queue>
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 vị trí thích hợp trong std::priority_queue (dựa trên độ ưu tiên), 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::priority_queue.
Giá trị trả về
Không có giá trị trả về
Đặc điểm
- 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, 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. - 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. - 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ử. - Dựa trên underlying container và hàm so sánh:
emplace()
của std::priority_queue sử dụng các hàm của underlying container (ví dụ:emplace_back()
của std::vector) và hàm so sánh để chèn và sắp xếp phần tử. - 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::priority_queue, cho phép dùngemplace()
ngay cả khi kiểu phần tử không hỗ trợ copy/move constructor. - 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ủavalue_type
ném ngoại lệ,emplace()
cũng sẽ ném ngoại lệ. - Độ phức tạp: Độ phức tạp của
emplace()
làO(log n)
, với n là số phần tử trong std::priority_queue. Giống với độ phức tạp củapush()
.
Ví dụ
#include <iostream>
#include <queue>
#include <string>
int main() {
std::priority_queue<std::pair<int, std::string>> mypq;
// Thêm một phần tử mới vào priority_queue, sử dụng emplace()
mypq.emplace(30, "World");
mypq.emplace(10, "Hello");
mypq.emplace(20, "C++");
// In ra các phần tử trong priority_queue
std::cout << "mypq:";
while (!mypq.empty()) {
std::cout << " (" << mypq.top().first << ", " << mypq.top().second << ")"; // Output: mypq: (30, World) (20, C++) (10, Hello)
mypq.pop();
}
std::cout << '\n';
return 0;
}
Với class không hỗ trợ copy/move constructor:
#include <iostream>
#include <queue>
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::priority_queue<NonCopyable> mypq; // Mặc định là max-heap, không phù hợp với NonCopyable
// Cần sử dụng cấu trúc so sánh tùy chỉnh để tạo min-heap
auto compare = [](const NonCopyable& a, const NonCopyable& b) { return a.data > b.data; };
std::priority_queue<NonCopyable, std::vector<NonCopyable>, decltype(compare)> mypq2(compare);
// mypq.push(NonCopyable(10)); // Error: Copy constructor is deleted
mypq2.emplace(10); // OK: Constructs the element in-place
mypq2.emplace(20); // OK: Constructs the element in-place
return 0;
}
Các hàm liên quan
push | Thêm một phần tử mới vào std::priority_queue |
pop | Xóa phần tử có độ ưu tiên cao nhất (phần tử ở đỉnh) của std::priority_queue |