2016-03-09 30 views
12

Là một followup để this question, bộ cấp mặc định (std::allocator<T>) là bắt buộc để thực hiện construct như sau (theo [default.allocator]):Cấu trúc cấp phát có nên() khởi tạo mặc định thay vì khởi tạo giá trị không?

template <class U, class... Args> 
void construct(U* p, Args&&... args); 

Hiệu ứng: ::new((void *)p) U(std::forward<Args>(args)...)

Tức là, luôn luôn khởi tạo giá trị. Kết quả của việc này là std::vector<POD> v(num), đối với bất kỳ loại nhóm nào, sẽ khởi tạo giá trị num yếu tố - đó là tốn kém hơn so với các yếu tố khởi tạo mặc định num.

Tại sao không & dagger;std::allocator cung cấp mặc định khởi tạo quá tải bổ sung? Tức là, giống như (mượn từ Casey):

template <class U> 
void construct(U* p) noexcept(std::is_nothrow_default_constructible<U>::value) 
{ 
    ::new(static_cast<void*>(p)) U; 
} 

Có lý do để khởi tạo giá trị trong trường hợp cuộc gọi không? Nó có vẻ ngạc nhiên với tôi rằng điều này phá vỡ các quy tắc C++ thông thường, nơi chúng tôi chỉ trả tiền cho những gì chúng tôi muốn sử dụng.


& dagger; Tôi cho rằng sự thay đổi này là không thể, vì hiện tại std::vector<int> v(100) sẽ cung cấp cho bạn 100 0, nhưng tôi tự hỏi tại sao lại như vậy ... cho rằng người ta có thể dễ dàng yêu cầu std::vector<int> v2(100, 0) theo cách tương tự có sự khác biệt giữa new int[100]new int[100]{}.

+0

Xem [P0040] (http: //www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0040r3.html) được chấp nhận gần đây. – FrankHB

+0

@FrankHB Giấy đó có thay đổi thứ mà 'vector' sẽ làm ở đây không? Nó chỉ thêm thuật toán vào thư viện chuẩn phải không? – Barry

+0

Phải. Vì vậy, nó không phải là một câu trả lời, chỉ là một bình luận. Nó cung cấp giao diện thuận tiện để dễ dàng thực hiện cách giải quyết của bạn. – FrankHB

Trả lời

2

Trong C++ 03 allocators construct viên mất hai đối số: con trỏ và giá trị được sử dụng để thực hiện sao chép khởi:

20.1.6 Bảng 34

a.construct(p,t)

Hiệu lực thi hành:
::new((void*)p) T(t)

construct lấy hai tham số có thể là traced back to 1994 (pg. 18). Như bạn có thể thấy, trong khái niệm Stepanov orignal nó không phải là một phần của giao diện phân bổ (nó không được cho là có thể cấu hình được) và đã hiện diện giống như trình bao bọc trên vị trí mới.

Cách duy nhất để biết chắc chắn sẽ hỏi bản thân Stepanov, nhưng tôi cho rằng lý do đó là sau: nếu bạn muốn xây dựng một cái gì đó, bạn muốn khởi tạo nó với giá trị cụ thể. Và nếu bạn muốn số nguyên của bạn chưa được khởi tạo, bạn chỉ có thể bỏ qua cuộc gọi construct vì nó không cần thiết cho các loại POD. Sau đó construct và các chức năng liên quan khác đã được gộp vào các bộ phân bổ và vùng chứa đã được tham số hóa trên chúng, giới thiệu một số mất kiểm soát khi khởi tạo cho người dùng cuối. Vì vậy, có vẻ như thiếu khởi tạo mặc định là vì lý do lịch sử: không ai biết về tầm quan trọng của nó khi C++ được chuẩn hóa và các phiên bản sau của tiêu chuẩn sẽ không đưa ra thay đổi đột ngột.

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