2011-01-29 29 views
11

Theo documentation nó:Boost :: unordered_map.emplace (Args && ... args) hoạt động như thế nào?

Chèn một đối tượng, xây dựng với args lập luận, trong vùng chứa nếu và chỉ nếu không có phần tử trong container với một chìa khóa tương đương.

Nhưng các đối tượng duy nhất có thể được chèn vào một unordered_map có loại std::pair<Key const, Mapped> (vì cả khóa và giá trị cần thiết cho một đối tượng được chèn), được biết để có một nhà xây dựng với chính xác hai đối số. Vậy tại sao nó sử dụng dạng hàm variadic? Chắc chắn có điều gì đó tôi hoàn toàn không hiểu về điều này.

Trả lời

8

Xem this SO bài viết trên emplace_back vs. push_back. Về cơ bản, nó cho phép một đối tượng được xây dựng từ các đối số được truyền vào nó mà không cần phải tạo đối tượng được truyền vào đầu tiên. Nó tiết kiệm trên đầu bằng cách loại bỏ một bản sao xây dựng mà thường xảy ra như là kết quả của việc tạo ra các đối tượng được chèn vào.

Vì vậy, bạn có thể nhận được ngay với điều này:

unordered_map<int,int> foo; 
foo.emplace(4, 5); 

thay vì

foo.insert(std::make_pair(4, 5)); 

Thậm chí tốt hơn, (và nếu tôi không nhầm), bạn có thể đi qua tuyến đường này:

struct Bar{ 
    int x,y; 
    Bar(int _x, int _y) : x(_x), y(_y){} 
}; 

unordered_map<int,Bar> baz; 
baz.emplace(4, 5, 6); 

Và được lấy từ Wiki trên C++0x:

Do tính chất của từ ngữ tham chiếu rvalue và một số sửa đổi đối với từ ngữ cho tham chiếu lvalue (tham chiếu thông thường), tham chiếu rvalue cho phép nhà phát triển cung cấp chức năng chuyển tiếp hoàn hảo. Khi kết hợp với các mẫu variadic, khả năng này cho phép các mẫu chức năng có thể chuyển tiếp hoàn toàn các đối số đến một hàm khác mà lấy các đối số cụ thể đó. Điều này hữu ích nhất cho việc chuyển tiếp các tham số của hàm tạo, để tạo các hàm nhà máy sẽ tự động gọi hàm tạo chính xác cho các đối số cụ thể đó.

Những tác phẩm theo cách thức sau đây:

template<typename TypeToConstruct> struct SharedPtrAllocator { 

    template<typename ...Args> std::shared_ptr<TypeToConstruct> construct_with_shared_ptr(Args&&... params) { 
     return std::shared_ptr<TypeToConstruct>(new TypeToConstruct(std::forward<Args>(params)...)); 
    } 
} 

Một lần nữa, không biết xấu hổ bị đánh cắp từ bài viết Wiki nêu trên.

+0

Ví dụ sau có vẻ lạ đối với tôi. Giả sử chúng ta có 2 hàm tạo cho 'Key':' Key (int) 'và' Key (int, int) 'và 2 cho' Value': 'Value (int, int)' và 'Value (int)', như thế nào trình biên dịch sẽ làm tê liệt trong trường hợp xây dựng một cặp 'Key/Value'? –

+0

Người đến trước dùng trước? Vì vậy, nó tạo ra một 'X (int, int)' đầu tiên và sau đó là một 'X (int)'. Sẽ kiểm tra nó sau và đăng lại. Cũng có thể không biên dịch và ném một lỗi thời gian biên dịch "phi thường". – Xeo

+0

@Matthieu M. Không có ý tưởng, thực sự. Vấn đề là thông số kỹ thuật hiện tại không được chính thức hóa đầy đủ và vì vậy chúng tôi không thể biết chắc chắn loại câu hỏi này được cho là sẽ được trả lời cho đến khi nào. Những gì chúng tôi cần là một luật sư ngôn ngữ để đi qua và làm sáng tỏ bất cứ điều gì mơ hồ câu trả lời của tôi có. Tôi muốn bỏ phiếu đó trong một nhịp tim. – wheaties

5

Bây giờ Thư viện chuẩn C++ đã tích hợp một phần của Boost:

Từ http://en.cppreference.com

#include <iostream> 
#include <utility> 
#include <tuple> 

#include <unordered_map> 

int main(){ 
    std::unordered_map<std::string, std::string> m; 

    // uses pair's piecewise constructor 
    m.emplace(std::piecewise_construct, 
     std::forward_as_tuple("c"), 
     std::forward_as_tuple(10, 'c')); 

    for (const auto &p : m) { 
     std::cout << p.first << " => " << p.second << '\n'; 
    } 
} 

std::piecewise_construct là một hằng số mà không để lại mơ hồ về cách các đối số sẽ được sử dụng

  • Tuple đầu tiên sẽ được sử dụng để con cấu trúc khóa
  • Thứ hai để tạo giá trị
Các vấn đề liên quan