2016-08-05 22 views
8

Được xây dựng với this online compiler, đoạn code sau:Tại sao không thể std :: tuple <int> có thể sao chép một cách trivially?

#include <iostream> 
#include <type_traits> 
#include <tuple> 

int main() { 
    std::cout << std::is_trivially_copyable<std::tuple<int>>::value << std::endl; 
    std::cout << std::is_trivially_copyable<std::pair<int, int>>::value << std::endl; 

    std::cout << std::is_trivial<std::tuple<int>>::value << std::endl; 
    std::cout << std::is_trivial<std::pair<int, int>>::value << std::endl; 
    return 0; 
} 

kết quả đầu ra:

0 
0 
0 
0 

tôi nhận được kết quả tương tự với Visual Studio 2015.

Tại sao là trường hợp? Có một lý do hợp lệ nào là std::tuple của các loại POD, không nói một cách đơn giản std::pair, không thể sao chép một cách trivially? Tôi đoán việc triển khai của họ cung cấp một số toán tử gán tùy chỉnh, nhưng chúng sẽ khác với các phiên bản mặc định được trình biên dịch tạo ra như thế nào?

+1

http://stackoverflow.com/questions/36625317/error-cannot-pass-objects-of-non-trivially-copyable-type-through ngụ ý rằng tiêu chuẩn không yêu cầu nó, vì vậy việc triển khai không làm phiền – happydave

Trả lời

7

Điều mà chuyến đi pair lên đến mức có thể sao chép tầm thường là có liên quan là tiêu chuẩn không yêu cầu rằng các nhà điều hành chuyển nhượng sao chép/di chuyển là tầm thường. Tiêu chuẩn này tuyên bố rõ ràng rằng các nhà xây dựng sao chép/di chuyển được mặc định, nhưng không phải như vậy đối với các bài tập. Một triển khai có thể mặc định chúng là tốt, nhưng tiêu chuẩn không yêu cầu nó.

Không có lý do thực sự tốt lý do tại sao tiêu chuẩn không yêu cầu nó. Nhưng nó không.

Đối với tuple, mọi thứ là phức tạp hơn. Nhiều việc triển khai tuple dựa trên việc có bộ đệm lưu trữ đúng kích cỡ/căn chỉnh và sử dụng vị trí new để xây dựng các thành viên riêng lẻ trong bộ đệm đó. Đó là tất cả tốt và tốt, nhưng một loại như vậy đã thực hiện một nhà xây dựng sao chép/di chuyển thủ công, vì nó phải gọi các nhà xây dựng sao chép/di chuyển của từng loại. Ngay cả khi nó biết rằng tất cả họ đều có thể sao chép một cách dễ dàng và sao chép chúng qua memcpy, đó vẫn là một thao tác thủ công. Và điều đó không đủ điều kiện từ bản sao tầm thường.

Hiện tại, có các bản triển khai tuple có thể sao chép một cách nhỏ gọn nếu các loại này có thể sao chép được một cách không đáng kể. Nhưng không có yêu cầu để thực hiện chúng theo cách đó. Và nó sẽ làm phức tạp việc triển khai tuple rất nhiều để yêu cầu họ thực hiện chính nó theo một cách nếu tất cả các loại đều có thể sao chép một cách trivially và thực hiện chúng theo một cách khác.

6

Bởi vì std::tuple có các nhà khai thác bản sao/di chuyển và các toán tử gán, điều này làm cho lớp không đáng kể có thể sao chép được.

Xem cpp reference:

Một lớp trivially copyable là một lớp học mà

Has no non-trivial copy constructors (this also requires no virtual functions or virtual bases) 
Has no non-trivial move constructors 
Has no non-trivial copy assignment operators 
Has no non-trivial move assignment operators 
Has a trivial destructor 

Nhưng std::tuple có tất cả các nhà thầu trên và toán tử gán.

+0

Câu trả lời không hoàn chỉnh nếu không chứng minh rằng các hàm thành viên đặc biệt của tuple là không tầm thường. –

+1

Bằng cách xác định [std :: tuple] (http://en.cppreference.com/w/cpp/utility/tuple) 's sao chép/di chuyển ctors/bài tập, nó đã có nghĩa là ctors/nhà khai thác không phải là tầm thường. – Mine

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