2012-12-19 37 views
5

thể trùng lặp:
initializer_list and move semanticsCó an toàn khi di chuyển các phần tử của danh sách khởi tạo không?

Trong mã này:

#include <vector> 
#include <initializer_list> 

template<typename T> 
class some_custom_container : public std::vector<T> 
{ 
public: 
    some_custom_container(const std::initializer_list<T>& contents) 
    { 
     for (auto& i : contents) 
     this->emplace_back(std::move(i)); 
    } 
}; 

class test_class 
{}; 

int main() 
{ 
    test_class a; 

    some_custom_container<test_class> i = { a, test_class(), a }; 
} 

Nếu tôi đã hiểu nó, tất cả các đối tượng trong { a, test_class(), a } được an toàn-xây dựng: các named- các đối tượng được sao chép và các đối tượng chưa được đặt tên được di chuyển để xây dựng initializer_list. Sau đó, initializer_list này được chuyển bằng tham chiếu đến hàm tạo của some_custom_container.

Sau đó, để tránh những bản sao vô dụng, tôi di chuyển tất cả chúng để điền vào vectơ.

Nhà xây dựng này có an toàn không? Tôi có nghĩa là, trong một tình huống kỳ lạ, ví dụ nếu T được đánh giá là một tham chiếu & hoặc & &, là vectơ luôn luôn chứa đầy (có chứa các đối tượng an toàn) không?

Nếu trường hợp này xảy ra, tại sao việc triển khai thực hiện các công cụ xây dựng initializer_list của các vùng chứa stl không được triển khai theo cách này? Như tôi biết, các nhà xây dựng của họ sao chép và không di chuyển nội dung.

+0

Nó thậm chí không biên dịch bởi vì danh sách trình khởi tạo chỉ cung cấp quyền truy cập const vào nội dung của chúng và bạn không thể di chuyển từ tham chiếu đến const. Xem thêm: http://stackoverflow.com/questions/8468774/can-i-list-initialize-a-vector-of-move-only-type –

+2

Điều đó sẽ không ngăn nó biên dịch, chỉ di chuyển. Trình tạo bản sao sẽ được gọi. – Puppy

Trả lời

4

initializer_list chỉ cung cấp quyền truy cập const vào các yếu tố của nó. Bạn có thể sử dụng const_cast để làm cho mã đó biên dịch, nhưng sau đó di chuyển có thể kết thúc với hành vi không xác định (nếu các phần tử của initializer_list thực sự là const). Vì vậy, không phải là không an toàn để làm việc này. Có are workarounds for this, nếu bạn thực sự cần nó.

+0

Hãy xem xét các thành phần trong được mô tả trên cpptruths (http://cpptruths.blogspot.com/2013/09/21-ways-of-passing-parameters-plus-one.html). Ý tưởng là để xác định lvalue/rvalue tại thời gian chạy và sau đó gọi di chuyển hoặc sao chép-xây dựng. trong sẽ phát hiện rvalue/lvalue mặc dù giao diện chuẩn được cung cấp bởi initializer_list là tham chiếu const. – Sumant

+0

@Sumant Điều đó có gây ra bất kỳ lợi ích có thể đo lường nào về hiệu suất hay sử dụng bộ nhớ, và nếu như vậy, một lượng lớn các lợi ích như vậy sẽ bù đắp được mức độ khủng khiếp của nó và thực tế mất khoảng một giờ để tìm ra cố gắng làm? Tôi nghi ngờ điều đó. –

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