Tôi tự hỏi, chính xác bảo đảm an toàn ngoại lệ cho std::vector::insert
là gì? Tôi quan tâm đến cả hai đối số đơn và phạm vi quá tải của hàm này.Bảo đảm an toàn ngoại lệ của vector :: chèn là gì?
Trả lời
Việc bảo lãnh chính xác được đưa ra trong C++ 11 23.3.6.5:
Nếu một ngoại lệ được ném khác hơn là bởi các nhà xây dựng sao chép, di chuyển nhà xây dựng, nhà điều hành chuyển nhượng, hoặc di chuyển điều hành giao
T
hoặc bằng bất kỳ hoạt độngInputIterator
nào cũng không có hiệu ứng. Nếu một ngoại lệ được ném bởi hàm tạo di chuyển của một số khôngCopyInsertable
T
, thì các hiệu ứng sẽ không được chỉ định.
Điều này có nghĩa gì với 'không có hiệu ứng'? Điều gì sẽ xảy ra với các phần tử đã được gán trong vectơ? – RedX
@RedX: Điều đó có nghĩa là không có hiệu ứng; mọi thứ được phục hồi về trạng thái ban đầu, như thể không có gì xảy ra. Nếu đã có các phần tử đã được gán, thì ngoại lệ phải được ném bởi "hàm tạo bản sao, di chuyển hàm tạo, toán tử gán, hoặc di chuyển toán tử gán của' T' hoặc bởi bất kỳ thao tác 'InputIterator' nào", trong trường hợp đó không có sự bảo đảm như vậy . –
Vì vậy, điều này ngụ ý đảm bảo cơ bản cho nếu các nhà xây dựng bản sao của T ném? – Puppy
Nếu phương pháp insert
chèn một phần tử đơn lẻ vào cuối danh sách và không yêu cầu bất kỳ bộ nhớ nào được cấp phát, hãy cung cấp bảo đảm ngoại lệ mạnh.
Nếu nó phải thêm nhiều hơn một phần tử hoặc phải cấp phát bộ nhớ, nó cung cấp bảo đảm ngoại lệ cơ bản. Boost có mô tả tốt về bảo đảm ngoại lệ.
Đảm bảo cơ bản: rằng các bất biến của thành phần được giữ nguyên và không có tài nguyên nào bị rò rỉ. Đảm bảo mạnh mẽ: rằng hoạt động đã hoàn tất thành công hoặc ném một ngoại lệ, để trạng thái chương trình chính xác như trước khi bắt đầu hoạt động. Đảm bảo không đảm bảo: hoạt động sẽ không loại trừ ngoại lệ.
Điều này có nghĩa là sau một ngoại lệ, bạn biết rằng vector
sẽ có thể sử dụng được, nhưng có thể không có tất cả dữ liệu bạn đã chèn vào. Tất cả các đối tượng đã được chèn thành công sẽ được xây dựng hoàn chỉnh.
Nói chung, hình thức-yếu tố duy nhất của insert
có một bảo đảm ngoại lệ mạnh mẽ cho bất kỳ container theo [container.requirements.general]/10, nhưng vector::insert
là một ngoại lệ cho quy tắc này:
[vector .modifiers]/1 áp dụng cho vector::insert
; InputIterator
ở đây đề cập đến tình trạng quá tải của insert
chèn một phạm vi.
Nếu một ngoại lệ được ném khác hơn là bởi các nhà xây dựng sao chép, di chuyển nhà xây dựng, nhà điều hành chuyển nhượng, hoặc di chuyển điều hành giao
T
hoặc bởi bất kỳ hoạt độngInputIterator
không có tác dụng. Nếu một ngoại lệ được ném bởi hàm tạo-di chuyển của một khôngCopyInsertable
T
, các hiệu ứng không được chỉ định.
vector
là nơi chứa cấp phát-aware, có nghĩa là nó sử dụng một cấp phát cho phân bổ bộ nhớ và xây dựng các yếu tố của nó [container.requirements.general]/3
Đối các thành phần bị ảnh hưởng bởi điều này mà tuyên bố một
allocator_type
, các đối tượng được lưu trữ trong các thành phần này phải được xây dựng bằng cách sử dụng chức năngallocator_traits<allocator_type>::construct
và bị phá hủy bằng chức năngallocator_traits<allocator_type>::destroy
. Các hàm này chỉ được gọi cho loại phần tử của vùng chứa, không phải cho các loại nội bộ được vùng chứa sử dụng.
Tôi nghĩ rằng điều này ngụ ý rằng các đối tượng cục bộ, không phải là thành phần của vùng chứa, có thể được tạo mà không sử dụng trình cấp phát (ví dụ: sao chép và trao đổi). Nếu không, các yêu cầu trên các ctors của kiểu giá trị sẽ là vô nghĩa; chức năng construct
của người cấp phát có thể có các bảo đảm ngoại lệ khác với hàm ctor của loại giá trị.
CopyInsertable
được quy định tại [container.requirements.general]/13 bằng cách yêu cầu
allocator_traits<A>::construct(m, p, v);
là tốt được hình thành; nơi A
là loại cấp phát, m
là loại A
, p
là một con trỏ đến T
, v
là một biểu hiện của loại (const
) T
, và T
là kiểu giá trị của container. Đây là một xây dựng tại chỗ từ một đối số (bản sao hoặc di chuyển-xây dựng).
Tương tự, MoveConstructible
được chỉ định, nhưng v
là (luôn luôn) giá trị của loại T
. EmplaceConstructible
theo cùng một biểu mẫu cho số không hoặc nhiều đối số thay vì v
.
Chức năng insert
cho các vùng chứa chuỗi áp đặt các yêu cầu khác nhau về loại giá trị cho các dạng khác nhau của nó [sequence.reqmts]; ở đây bao gồm cả yêu cầu bổ sung cho vector
:
- cho một đối số duy nhất đó là một vế trái của loại (
const
)T
và cho chèn hình thức N bản sao của,T
sẽCopyInsertable
vàCopyAssignable
- cho một đơn Lập luận đó là một rvalue loại
T
,T
sẽMoveInsertable
vàMoveAssignable
- đối với hình thức phạm vi,
T
sẽEmplaceConstructible
từ các biến lặp không quan tâm (*); thêm vào đó,MoveInsertable
vàMoveAssignable
nếu lặp của dãy núi này có lặp về phía trước
(*) Lưu ý: EmplaceConstructible
chỉ từ lặp dereferenced là không đủ nếu container phải được thay đổi kích cỡ cho chèn (và, ví dụ như *i
cho một trình lặp như vậy không thuộc loại giá trị). Có thể đặc điểm kỹ thuật yêu cầu biểu mẫu phạm vi để kế thừa các yêu cầu của biểu mẫu phần tử đơn, tức là MoveAssignable
hoặc CopyAssignable
.
Nhận xét bên: Biểu mẫu phạm vi insert
yêu cầu hai trình vòng lặp không trỏ vào vùng chứa mà chúng được chèn vào.
tôi giải thích các thông số kỹ thuật ngoại lệ như sau:
Báo cáo bổ sung về CopyInsertable
trong đặc tả ngoại lệ của vector::insert
lẽ phân biệt giữa bảo lãnh cơ bản và không có bảo đảm: Các dtor của một container thường được yêu cầu để gọi các dtor của tất cả các yếu tố và deallocate tất cả bộ nhớ (trong các yêu cầu container chung). Đó là, trừ khi hành vi không xác định/không xác định, bảo đảm cơ bản giữ.
Tại sao có yêu cầu kết hợp CopyInsertable
và di chuyển-ctor (thay vì allocator::construct
với giá trị), tôi không biết. Các di chuyển-ctor chỉ được sử dụng trực tiếp cho các đối tượng không phải là yếu tố của container (gián tiếp có thể thông qua allocator::construct
).
Các nhận xét khác về "không có hiệu ứng" (-> đảm bảo mạnh) là không áp dụng cho các hoạt động cấp phát (construct
). Các hoạt động cấp phát rõ ràng không phải là không nhận diện. Vì bạn có thể cung cấp một trình cấp phát không mặc định không sử dụng bản sao và di chuyển-ctor của loại giá trị cho construct
, insert
phải cung cấp bảo đảm ngoại lệ mạnh ngay cả đối với các hoạt động cấp phát construct
. Ví dụ, nếu số phân bổ construct
của người cấp phát không phải là ngoại lệ, trong khi thay đổi kích thước, các phần tử không thể di chuyển được xây dựng nhưng phải được sao chép.
Chuyển nhượng và chuyển nhượng phải không được chấp nhận đối với đảm bảo mạnh vì các yếu tố có thể cần được dịch chuyển xung quanh cho insert
; copy- và move-ctor có thể cần phải không được chấp nhận cho sự bảo đảm mạnh mẽ vì các đối tượng địa phương được tạo ra trong thuật toán.
- 1. C++ an toàn ngoại lệ
- 2. Đảm bảo an toàn loại trên biểu thức lambda chung
- 3. An toàn ngoại lệ trong Qt
- 4. Đảm bảo rằng mã của tôi là an toàn chủ đề
- 5. Java: là lớp ngoại lệ có an toàn không?
- 6. Đảm bảo không đảm bảo VirtualMachineError
- 7. An toàn ngoại lệ và make_unique
- 8. Enable Xử lý ngoại lệ an toàn trong C++ Builder
- 9. Đảm bảo rằng Ngoại lệ luôn bị vô hiệu
- 10. msdn: "An toàn chủ đề" là gì?
- 11. Trình lọc HTML làm gì để đảm bảo lập trình PHP an toàn?
- 12. Chi phí từ shared_ptr là an toàn chỉ là gì?
- 13. Lặp lại qua Collections.synchronizedSet (...). ForEach() có đảm bảo là luồng an toàn không?
- 14. Mã an toàn ngoại lệ và di chuyển ngữ nghĩa
- 15. Trong Java, Làm cách nào để đảm bảo ứng dụng web của tôi an toàn?
- 16. Làm thế nào để đảm bảo an toàn luồng của phương pháp tĩnh tiện ích?
- 17. Viết mã an toàn ngoại lệ đa luồng
- 18. "ói mửa ngoại lệ" là gì?
- 19. Đang truy cập con trỏ thô sau std :: vector :: bảo lưu an toàn?
- 20. Là chủ đề của ImmutableList.Builder có an toàn không?
- 21. Ngoại lệ bảo mật
- 22. Đảm bảo fgetcsv() đọc toàn bộ dòng
- 23. std :: vector, chủ đề an toàn, đa luồng
- 24. Đảm bảo an toàn chủ đề trên phương pháp tĩnh Trong C#
- 25. Sử dụng 'typedef' để đảm bảo an toàn loại hợp lý
- 26. Bảo mật kênh TCP mở, an toàn là bao lâu?
- 27. Định tuyến an toàn là gì?
- 28. Logic của trình lặp không an toàn là gì?
- 29. Loại an toàn trong .net là gì?
- 30. Làm cách nào để đảm bảo an toàn luồng trong ngữ cảnh sau?
Điều này phụ thuộc rất nhiều vào loại được lưu trữ trong vùng chứa –
@David: Bạn chính xác. Tôi quan tâm đến trường hợp nó không có động thái không rõ ràng - ví dụ: chỉ ném bản sao. – Puppy