2016-01-22 15 views
6

tôi chút bối rối về cách tiêu chuẩn điều chỉnh trường hợp này:std :: di chuyển và bản đồ phân

struct Foo { 
    Foo & operator = (std::string xxx) 
    { 
     x = std::move(xxx); 
     return *this; 
    } 

    std::string x; 
}; 

std::map<std::string, Foo> bar; 

std::string baz = "some string"; 

bar[baz] = std::move(baz); 

trình biên dịch có thể tạo ra mã để baz sẽ được chuyển trước nó được sử dụng để khởi tạo và nhận được tham chiếu đến yếu tố trong bar (để khởi tạo std::string xxx)? Hoặc mã này có an toàn và không có hành vi không xác định?

+1

Nó không phải UB, nhưng không được bảo đảm để làm việc, một trong hai. –

+0

Xem [this] (http://coliru.stacked-crooked.com/a/5ef8993192148d84) phiên bản đơn giản của mã của bạn. 'std :: map' và toán tử gán không cần phải tham gia để điều này xảy ra, và sự hiện diện của chúng không thay đổi vấn đề cơ bản với mã. – Mankarse

+0

@Mankarse, vâng, thực sự, mọi thứ có thể được đun sôi xuống đến trường hợp này – GreenScape

Trả lời

11

Địa ngục không. Các biểu hiện là, vâng, tương đương với

(bar.operator[](baz)).operator=(std::move(baz)) 

Nhưng không có trật tự được bảo đảm giữa việc đánh giá (bar.operator[](baz)).operator= - chính thức, các postfix thể hiện chỉ định các chức năng để được gọi là - và việc thẩm định khởi của đối số đến operator=, đó là điều di chuyển từ baz.

Trong thực tế, this asserts on GCC:

std::map<std::string, Foo> bar; 
std::string baz = "some string"; 
bar[baz] = std::move(baz); 
assert(bar.count("some string")); 
+1

Cảm ơn bạn! Đây là những gì tôi nghĩ bản thân mình, chỉ muốn có một xác nhận từ người khác. – GreenScape

Các vấn đề liên quan