2010-03-16 28 views
7

tôi chỉ viết một số mã để kiểm tra hành vi của std :: bình đẳng, và đã đi ngạc nhiên:C++ std :: bình đẳng - lý do đằng sau không thử nghiệm cho 2 phạm vi có kích thước bằng nhau?

int main() 
{ 
    try 
    { 
    std::list<int> lst1; 
    std::list<int> lst2; 

    if(!std::equal(lst1.begin(), lst1.end(), lst2.begin())) 
     throw std::logic_error("Error: 2 empty lists should always be equal"); 

    lst2.push_back(5); 

    if(std::equal(lst1.begin(), lst1.end(), lst2.begin())) 
     throw std::logic_error("Error: comparing 2 lists where one is not empty should not be equal"); 
    } 
    catch(std::exception& e) 
    { 
    std::cerr << e.what(); 
    } 
} 

Sản lượng (một bất ngờ đối với tôi):

Error: comparing 2 lists where one is not empty should not be equal 

Quan sát: tại sao nó std::equal không kiểm tra xem 2 container có cùng số size() không? Có lý do chính đáng nào không?

+0

Kiểm tra kích thước của danh sách không phải là thời gian không đổi - bạn phải lặp lại danh sách. –

+1

@Neil: Có thể có thời gian không đổi. Việc triển khai Microsoft có một thời gian không đổi 'size()'. Trong các yêu cầu vùng chứa, tiêu chuẩn C++ chỉ nói 'size()' _should_ có độ phức tạp thời gian không đổi. –

+0

Và việc thực hiện GCC có thời gian tuyến tính 'size()'. –

Trả lời

12

Quan sát: tại sao nó là tiêu chuẩn :: bằng không trước tiên kiểm tra xem 2 vùng chứa có cùng kích thước() không? Có lý do chính đáng nào không?

Làm cách nào? Bạn không vượt qua các thùng chứa cho hàm, bạn vượt qua trong các biến số vòng lặp. Hàm không có cách nào để biết kích thước của vùng chứa thứ hai. Tất cả những gì có thể làm là giả sử rằng người dùng đã vượt qua hai phạm vi vùng chứa hợp lệ (nghĩa là phạm vi thứ hai được chỉ định chính xác là khoảng thời gian nửa mở [lst2.begin(), lst2.begin() - lst1.begin() + lst1.end() [) và hành động tương ứng.

+0

Bạn nói đúng, Konrad.Tôi quên rằng tôi đã đi qua iterator đến std :: bằng nhau. Có nói rằng, có cái gì đó làm một cái gì đó như: bằng (lst1, lst2) được cung cấp bởi STL? – sivabudh

+1

@ ShaChris32: có, bạn có thể so sánh hai danh sách (hoặc nói chung là hai thùng chứa tiêu chuẩn cùng loại) với '=='. –

+1

@Mike: for real? D'oh! –

2

Nó cung cấp cho bạn câu trả lời đúng - bạn đã yêu cầu nó kiểm tra xem hai bình chứa có bằng nhau trong phạm vi lst1.begin() đến lst1.end() hay không. Bạn vẫn đang so sánh hai danh sách trống trong phạm vi equal(). Nếu bạn thay đổi mã để so sánh từ lst2.begin() đến lst2.end(), bạn sẽ nhận được những gì bạn mong đợi.

3

Vì kiểm tra kích thước có thể là hoạt động O(n).

+0

Không. Không có cách nào để biết kích thước của thùng chứa thứ hai. Thông tin này chỉ đơn giản là không có sẵn cho 'bằng', không trực tiếp hay gián tiếp. –

+0

@Konrad: Tất nhiên là: chỉ cần lặp lại cả hai danh sách từ đầu đến cuối và đếm số lượng phần tử. –

+0

@John: Làm thế nào bạn có được trình lặp kết thúc cho list2? – Bill

4

Bạn luôn có thể viết phiên bản của riêng bạn bằng mà không có hiệu quả những gì bạn muốn:

template <class InputIterator1, class InputIterator2> 
bool equalx(InputIterator1 first1, InputIterator1 last1, 
      InputIterator2 first2, InputIterator2 last2) 
{ 
    while ((first1 != last1) && (first2 != last2)) 
    { 
    if (*first1 != *first2) // or: if (!pred(*first1,*first2)), for pred version 
     return false; 
    ++first1; ++first2; 
    } 
    return (first1 == last1) && (first2 == last2); 
} 

Để chắc chắn rằng cả hai dãy có cùng một số yếu tố, chữ ký phải bao gồm dấu chấm hết cho thứ hai phạm vi.

0

C++ 14 đã thêm quá tải bốn đối số giống như câu trả lời trong câu trả lời của R Samuel Klatchko. Và ít nhất hai triển khai STL mà tôi đã kiểm tra (libC++ và MSVC) thực hiện tối ưu hóa việc kiểm tra khoảng cách-up-front rõ ràng cho các trình vòng lặp truy cập ngẫu nhiên.

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