std::unordered_multimap::emplace
#include <unordered_map>
template <class... Args>
std::pair<iterator, bool> emplace(Args&&... args);
Xây dựng (construct) một phần tử mới (cặp key-value
) trực tiếp trong std::unordered_multimap, tránh việc sao chép hoặc di chuyển không cần thiết. std::unordered_multimap cho phép các key trùng lặp, do đó emplace() sẽ luôn chèn phần tử mới vào std::unordered_multimap ngay cả khi key đã tồn tại.
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ặp
key-value
). Các đối số này sẽ được truyền đến constructor củastd::pair<const Key, T>
.
Giá trị trả về
iterator
- Trả về một iterator trỏ đến phần tử vừa mới được chèn vào.
Đặ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 std::unordered_multimap, 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ểustd::pair<const Key, T>
. - Có thể làm thay đổi iterator: Việc chèn phần tử vào std::unordered_multimap có thể làm thay đổi (invalidate) các iterator đang trỏ đến các phần tử trong std::unordered_multimap do việc rehash có thể xảy ra.
- Phân biệt với
insert()
: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 std::unordered_multimap, 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ủastd::pair<const Key, T>
ném ngoại lệ,emplace()
cũng sẽ ném ngoại lệ. - Luôn chèn phần tử: Không giống như emplace() của std::unordered_map, emplace() của std::unordered_multimap luôn chèn phần tử mới, ngay cả khi key đã tồn tại.
- Độ phức tạp: Độ phức tạp trung bình của
emplace()
làO(1)
, trường hợp xấu nhất làO(n)
, với n là số phần tử trong std::unordered_multimap.
Ví dụ
#include <iostream>
#include <unordered_map>
#include <string>
int main() {
std::unordered_multimap<std::string, int> myumm;
// Chèn một phần tử mới vào unordered_multimap, sử dụng emplace()
auto it = myumm.emplace("apple", 1);
// In ra phần tử vừa chèn
std::cout << "Inserted element: (" << it->first << ", " << it->second << ")\n";
// Chèn thêm các phần tử khác
myumm.emplace("banana", 2);
myumm.emplace("orange", 3);
myumm.emplace("apple", 4); // Chèn thêm bản sao của key "apple"
// In ra các phần tử trong unordered_multimap
std::cout << "myumm:\n";
for (const auto& p : myumm) {
std::cout << " (" << p.first << ", " << p.second << ")";
}
std::cout << '\n';
// Output:
// myumm:
// (orange, 3) (banana, 2) (apple, 1) (apple, 4) (thứ tự có thể khác)
return 0;
}
Với class không hỗ trợ copy/move constructor
#include <iostream>
#include <unordered_map>
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::unordered_multimap<int, NonCopyable> myumm;
// myumm.insert(std::make_pair(1, NonCopyable(10))); // Error: Copy constructor is deleted
myumm.emplace(1, 10); // OK: Constructs the element in-place
myumm.emplace(2, 20); // OK: Constructs the element in-place
return 0;
}
Các hàm liên quan
insert | Chèn một phần tử mới (cặp key-value ) vào std::unordered_multimap |
find | Tìm kiếm một phần tử có key bằng với giá trị key cho trước trong std::unordered_multimap |