2009-07-11 37 views
28

Bất cứ ai có thể giải thích tại sao không phải là toán tử [] thực hiện cho một danh sách std ::? Tôi đã tìm kiếm xung quanh một chút nhưng không tìm thấy câu trả lời. Nó sẽ không quá khó để thực hiện hoặc tôi thiếu một cái gì đó?Tại sao không có toán tử [] cho danh sách std ::?

Trả lời

65

Lấy một phần tử theo chỉ mục là một hoạt động O (n) cho danh sách liên kết, đó là những gì std::list là. Vì vậy, nó đã được quyết định rằng việc cung cấp operator[] sẽ là lừa đảo, vì mọi người sẽ bị cám dỗ để chủ động sử dụng nó, và sau đó bạn sẽ thấy mã như:

std::list<int> xs; 
for (int i = 0; i < xs.size(); ++i) { 
    int x = xs[i]; 
    ... 
} 

mà là O (n^2) - rất khó chịu. Vì vậy, tiêu chuẩn ISO C++ đề cập cụ thể rằng tất cả các chuỗi STL hỗ trợ operator[] nên làm điều đó trong thời gian cố định phân bổ (23.1.1 [lib.sequence.reqmts]/12), có thể đạt được cho vectordeque, nhưng không phải list.

Đối với trường hợp bạn thực sự cần điều đó đại loại như vậy, bạn có thể sử dụng std::advance thuật toán:

int iter = xs.begin(); 
std::advance(iter, i); 
int x = *iter; 
+0

Vì vậy, về cơ bản, nó chỉ là vấn đề ngăn chặn người phạm sai lầm? –

+17

yep.Hoặc không hứa hẹn bạn không thể giữ được. Trong STL, toán tử [] hứa hẹn * hiệu quả * truy cập vào các phần tử tùy ý. – jalf

+0

Và cảm ơn Pavel đã tham khảo chuẩn C++! –

3

Nó sẽ không quá khó (đối với người triển khai) nhưng nó sẽ là quá khó khăn trong thời gian chạy, vì hiệu suất sẽ là khủng khiếp trong hầu hết các trường hợp. Buộc người dùng đi qua từng liên kết sẽ làm cho nó rõ ràng hơn những gì đang xảy ra trong đó hơn 'myList [102452]' sẽ.

+0

Để xây dựng một toán tử bit [] là hoạt động thời gian không đổi ở tất cả các vị trí khác được sử dụng. Việc đặt cùng tên cho một hoạt động O (n) sẽ không nhất quán và khó hiểu. – dmckee

+0

Vâng, nó là O (log n) trong một bản đồ nhưng tôi nhận được quan điểm của bạn. –

+0

Trong bản đồ, nó không phải là một chỉ số vị trí, điều này khá rõ ràng - ngoại trừ có lẽ khi khóa bản đồ là một số nguyên, nhưng nếu bạn khó hiểu về truy cập vị trí bằng tra cứu chính, bạn có nhiều vấn đề lớn hơn;) –

1

Tôi nghĩ rằng tôi đã tìm thấy câu trả lời trong một SO gửi Extending std::list

"nhà điều hành của bạn [] là O (N) thời gian "- điều này là chính xác lý do tại sao nó không được bao gồm trong tiêu chuẩn std :: danh sách <>. - Michael Burr ngày 14 tháng 12 tại 17:29

Tuy nhiên, đó có phải là lý do duy nhất không?

CHỈNH SỬA: Dường như mọi người đã đề cập đến nó là vấn đề nhất quán về hiệu suất sau đó thực hiện nghiêm ngặt.

+0

Bạn có nghĩa là không đủ lý do? :-) –

+0

Đó là. Tìm kiếm ở đâu đó, .NET 'LinkedList' không cung cấp một trình chỉ mục cho các lý do chính yếu - nó chỉ quá lừa đảo. Theo truyền thống, khi một cái gì đó có một chỉ mục vị trí, nó được giả định rằng hoạt động là O (1). –

0

Trên thực tế, có hoàn toàn không có lý do gì để không cung cấp operator [] hoặc ít nhất là phương pháp tại (int), vì hai lý do:

  • Đây là danh sách liên kết đôi, vì vậy bạn cần phải di chuyển ở hầu hết kích thước()/2 nơi trình vòng lặp của bạn để lấy chỉ mục của bạn, và chi phí để giữ lại một vài vòng lặp cố định hơn là rất thấp. Và cuối cùng, thư viện Qt cung cấp toán tử [] và tại, và tôi không thấy chi phí hiệu năng sử dụng nó.
  • buộc người khác không sử dụng là thói quen lập trình rất xấu, vì danh sách sẽ sử dụng nhiều thùng chứa, nếu bạn có quyền truy cập ngẫu nhiên gần quyền truy cập được liên kết, có nhiều ví dụ khi bạn cần cả hai quyền truy cập mà thời gian chạy.
+0

Đây có phải là cơ sở hoàn toàn dựa trên ý kiến ​​của bạn hoặc bạn đã tạo ra một kịch bản thử nghiệm tốt đẹp, nơi bạn cho thấy việc triển khai tuỳ chỉnh của bạn về 'std :: list :: operator []' có hiệu quả không? (BTW, theo Stroustrup container tiêu chuẩn bạn nên sử dụng là 'std :: vector'). – Zeta

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