2012-11-01 26 views
20

xem xét như sau:Có an toàn khi sử dụng emplace_back với một thùng chứa unique_ptrs không?

std::vector<std::unique_ptr<int>> ptrsToInts; 
ptrsToInts.emplace_back(new int); 

Nếu phân bổ lại xảy ra trong vector, và thất bại (ném std::bad_alloc), tôi "an toàn" hay tôi sẽ bị rò rỉ một int?

C++ 11 23.3.6.5 [vector.modifiers]/1 nói:

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 động nào InputIterator không có hiệu ứng.

có vẻ như đây là vấn đề tiềm năng. Tức là, nếu có "không có hiệu ứng", thì không có unique_ptr nào được xây dựng, và do đó hành vi hủy diệt sẽ dựa vào delete con trỏ đó sẽ không xảy ra. (Có thể chỉ ra rằng emplace_back nên bị cấm đối với các thùng chứa unique_ptr s)

+1

Điểm tốt. Điều này đã truyền cảm hứng cho tôi từ bỏ việc sử dụng 'new' hoàn toàn có lợi cho' std :: make_unique', để tôi có thể biết mọi phân bổ kết thúc bằng một con trỏ thông minh từ đường đi. – GManNickG

+0

Tôi đã lưu ý sự cố này trong một nhận xét tại đây: http://stackoverflow.com/questions/3283778/why-can-i-not-push-back-a-unique-ptr-into-a-vector/3283795#3283795 –

Trả lời

18

Nếu tái phân bổ là cần thiết và không thành công, thì có, đối tượng của bạn không bao giờ đi vào vùng chứa và do đó sẽ bị mất.

Tuy nhiên, cần lưu ý rằng đây là lỗi người dùng thuần túy. emplace_back không nên "cấm" đối với các thùng chứa unique_ptr, bởi vì có cách hoàn toàn an toàn để thực hiện việc này (chẳng hạn như reserve nhập không gian trước đó, vì vậy bạn biết nó sẽ luôn ở đó). Ngoài ra, bạn có thể vượt qua toàn bộ unique_ptr s, vì nó hoàn toàn có khả năng sử dụng một hàm tạo di chuyển. Vì vậy, thực sự, đó là lỗi của bạn vì không đúng cách gói đối tượng không RAII của bạn (int*) trong một đối tượng RAII trước khi bạn có thể ném ngoại lệ.

+2

Ah - nhưng đối tượng không bao giờ thực hiện nó. Emplacement xây dựng đối tượng tại chỗ bên trong khối bộ nhớ vector. Những gì được truyền vào là một con trỏ, không phải là một 'unique_ptr'. Chắc chắn, con trỏ bị phá hủy, nhưng tôi có đảm bảo rằng các destructor của 'unique_ptr' chạy và xóa con trỏ? –

+0

Thực tế là 'emplace' là một no-op cho một ngoại lệ thay vì nói' int' không nhận 'xóa'd đúng, vì phân bổ của nó xảy ra hoàn toàn bên ngoài' emplace', trong khi việc xây dựng (deallocating) con trỏ thông minh xảy ra bên trong. –

+1

Erm, vì khi nào cần phải có "lỗi" được giao ở đây? Đối với việc có những cách "hoàn toàn an toàn" để làm điều này, chắc chắn, có những cách "an toàn" để làm điều đó. Nhưng nếu bạn buộc sử dụng một hàm tạo di chuyển, bạn cũng có thể chỉ sử dụng 'push_back', vì nó thực thi hành vi đúng trong mọi trường hợp. –

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