2010-04-12 16 views
9

Trong câu trả lời cho câu hỏi về std::stack::pop()I claimed lý do pop không trả lại giá trị là vì lý do an toàn ngoại lệ (điều gì sẽ xảy ra nếu trình tạo bản sao ném).Ngăn xếp có phương pháp an toàn ngoại lệ để trả lại và xóa phần tử trên cùng với ngữ nghĩa di chuyển không?

@Konrad đã nhận xét rằng giờ đây với ngữ nghĩa di chuyển, điều này không còn liên quan nữa. Điều này có đúng không?

AFAIK, di chuyển các nhà thầu canthrow, nhưng có lẽ với noexcept nó vẫn có thể đạt được.

Đối với điểm thưởng, đảm bảo an toàn luồng có thể cung cấp cho hoạt động này?

+2

Tôi tự hỏi điều gì sẽ xảy ra nếu bạn gọi 'std :: move' trên một loại mà không có nhà xây dựng di chuyển? Không biên dịch? Sử dụng constructor sao chép? – UncleBens

+3

@UncleBens, nó sử dụng hàm tạo bản sao. – Motti

Trả lời

3

Tất nhiên, không phải mọi loại đều được kích hoạt di chuyển và C++ 0x thậm chí cho phép các nhà thầu di chuyển ném. Miễn là xây dựng các đối tượng từ một rvalue có thể ném nó không thể được ngoại lệ an toàn. Tuy nhiên, di chuyển ngữ nghĩa cho phép bạn có nhiều loại không có khả năng xây dựng được cho một nguồn rvalue.

Hỗ trợ có điều kiện cho việc này có thể được thực hiện với SFINAE. Nhưng ngay cả khi không có chức năng thành viên có điều kiện như vậy, không có gì ngăn bạn viết:

auto stack = ...; 
auto elem = std::move_if_noexcept(stack.back()); 
stack.pop_back(); 

điều này đảm bảo sự đảm bảo mạnh mẽ ngay cả trong trường hợp nhà thầu di chuyển của bạn không đảm bảo.

+0

Vâng, nhưng bạn không thể sử dụng 'has_nothrow_move_constructor ' để tạo phương thức 'T' có một hàm tạo không di chuyển? – Motti

+4

@Motti: Vấn đề là bạn sẽ có các giao diện và hành vi khác nhau (không chỉ các triển khai) tùy thuộc vào việc các đối tượng được lưu trữ có di chuyển constructor hay không, do đó sẽ không thực sự là một ý tưởng hay. –

+2

@dribeas: nó sẽ là xấu cho có một chức năng pop trả về một cái gì đó nếu có một nhà xây dựng di chuyển, và void nếu không có? Trong trường hợp sử dụng phổ biến, bạn biết loại giá trị của stack (ví dụ: nếu nó là 'int', bạn có thể sử dụng giá trị trả về và nếu bạn sử dụng giá trị trả về khi bạn không nên biên dịch mã), hoặc bạn khác đang viết mã chung và không biết loại (trong trường hợp này bạn gắn bó với giao diện cũ). –

2

Đối với câu hỏi tiền thưởng, điều đó sẽ không cung cấp an toàn cho luồng. Hãy xem xét rằng, ví dụ, hầu hết việc triển khai std::vector có ba phần tử dữ liệu (con trỏ đến đầu bộ nhớ, con trỏ vượt quá kết thúc dữ liệu được sử dụng, con trỏ vượt quá bộ nhớ được phân bổ). Di chuyển ngữ nghĩa cho phép bạn di chuyển nội dung của véc-tơ mà không cần phải phân bổ lại và sao chép giá trị, nhưng điều đó không liên quan gì đến an toàn luồng. Bạn sẽ phải sử dụng các cấu trúc thread-safe để đề an toàn cấu trúc (như di chuyển không bao hàm bởi bất kỳ phương tiện nguyên tử)

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