Động cơ cho phần mở rộng này, có thể phát hiện được bởi một chương trình phù hợp, và do đó không phù hợp, là để làm cho vector<bool>
hành vi giống hơn vector<char>
đối với các tham chiếu (const và cách khác).
Giới thiệu
Kể từ năm 1998, vector<bool>
đã được chế giễu là "không phải là một container." LWG 96 , một trong những vấn đề đầu tiên của LWG, đã khởi động cuộc tranh luận. Ngày nay, 17 năm sau, vector<bool>
phần lớn vẫn không thay đổi.
Bài báo này đi vào một số ví dụ cụ thể về cách hoạt động của vector<bool>
khác với mọi cách diễn đạt khác vector
, do đó làm tổn hại đến mã chung. Tuy nhiên, cùng một bài báo thảo luận về độ dài các đặc tính hiệu suất rất tốt vector<bool>
có thể có nếu được triển khai đúng cách.
Tóm lại : vector<bool>
không phải là một thùng chứa tồi. Nó thực sự khá hữu ích. Nó chỉ có một cái tên xấu.
Quay lại const_reference
Như đã giới thiệu ở trên và chi tiết ở đây , điều tồi tệ vector<bool>
là nó hoạt động trong mã chung chung khác với các bản vector
thuyết minh khác . Đây là một ví dụ cụ thể:
#include <cassert>
#include <vector>
template <class T>
void
test(std::vector<T>& v)
{
using const_ref = typename std::vector<T>::const_reference;
const std::vector<T>& cv = v;
const_ref cr = cv[0];
assert(cr == cv[0]);
v[0] = 1;
assert(true == cv[0]);
assert(cr == cv[0]); // Fires!
}
int
main()
{
std::vector<char> vc(1);
test(vc);
std::vector<bool> vb(1);
test(vb);
}
Thông số kỹ thuật tiêu chuẩn nói rằng xác nhận được đánh dấu // Fires!
sẽ kích hoạt, nhưng chỉ khi test
được chạy với a vector<bool>
. Khi chạy với một vector<char>
(hoặc bất kỳ vector
bên cạnh bool
khi T
gán giá trị không mặc định thích hợp ), bài kiểm tra sẽ vượt qua.
Việc triển khai libc ++ đã tìm cách giảm thiểu các tác động tiêu cực của việc vector<bool>
cư xử khác nhau trong mã chung. Một điều nó đã làm để đạt được điều này là tạo vector<T>::const_reference
một tham chiếu proxy , giống như tham chiếu đã chỉ định vector<T>::reference
, ngoại trừ việc bạn không thể chỉ định thông qua nó. Đó là, trên libc ++, vector<T>::const_reference
về cơ bản là một con trỏ đến bit bên trong vector
, thay vì bản sao của bit đó.
Trên libc ++, ở trên test
chuyển cho cả vector<char>
và vector<bool>
.
Chi phí gì?
Nhược điểm là phần mở rộng này có thể phát hiện được, như trong câu hỏi. Tuy nhiên, rất ít chương trình thực sự quan tâm đến loại chính xác của bí danh này và nhiều chương trình hơn quan tâm đến hành vi.
Động cơ cho sự không tuân thủ này là gì?
Để cung cấp cho ứng dụng khách libc ++ hành vi tốt hơn trong mã chung và có lẽ sau khi kiểm tra thực địa đầy đủ, hãy đề xuất phần mở rộng này cho một tiêu chuẩn C ++ trong tương lai để cải thiện toàn bộ ngành C ++.
Một đề xuất như vậy có thể ở dạng một vùng chứa mới (ví dụ bit_vector
) có nhiều API giống như ngày nay vector<bool>
, nhưng với một vài nâng cấp như được const_reference
thảo luận ở đây. Tiếp theo là việc ngừng sử dụng (và cuối cùng là xóa bỏ) vector<bool>
chuyên môn. bitset
cũng có thể sử dụng một chút nâng cấp trong bộ phận này, ví dụ như thêm const_reference
và một tập hợp các trình vòng lặp.
Đó là, trong nhận thức muộn màng bitset
là vector<bool>
(mà nên được đổi tên thành bit_vector
- hoặc bất cứ điều gì), như array
là vector
. Và sự tương tự phải giữ đúng hay không chúng ta đang nói về bool
là value_type
của vector
và array
.
Có nhiều ví dụ về các tính năng C ++ 11 và C ++ 14 bắt đầu dưới dạng phần mở rộng trong libc ++. Đây là cách các tiêu chuẩn phát triển. Thực tế chứng minh kinh nghiệm thực địa tích cực có ảnh hưởng mạnh mẽ. Các tiêu chuẩn dân gian là một nhóm bảo thủ khi nói đến việc thay đổi các thông số kỹ thuật hiện có (như chúng phải như vậy). Đoán, ngay cả khi bạn chắc chắn mình đoán đúng, là một chiến lược mạo hiểm để phát triển một tiêu chuẩn được quốc tế công nhận.
vector<bool>
trên cơ sở hạng nhất hơn không?