2010-10-05 41 views
26

Giả sử tôi có một std::vector nói VectorKiểm tra liệu một vector rỗng

Bây giờ sau khi thực hiện một số hoạt động trên vector (hoặc chèn hoặc xóa) Tôi muốn kiểm tra xem các vector rỗng và trên cơ sở của tôi mà muốn thực hiện một số thao tác.

phương pháp nào là tốt hơn

Tiếp cận 1

if (Vector.size() == 0){ /* operations */ } 

Tiếp cận 2

if (Vector.empty()) { /* operations */ } 

Đó là một cách tiếp cận tốt hơn, 1 hoặc 2?

+0

https://stackoverflow.com/questions/743197/size-vs-empty-in-vector-why-empty-is-preferred – x29a

Trả lời

6

Phương pháp tiếp cận (2) sẽ tốt hơn vì empty() luôn chạy trong một thời gian không đổi [ví dụ: O(1)] bất kể loại vùng chứa.

size() quá chạy trong O(1) [cho std :: vector] mặc dù nó có thể chạy trong O(n) cho std:list [thats thực hiện quy định phải trung thực]

Trong Effective STL [Khoản 4] Scott Meyers nói

Bạn nên chọn cấu trúc sử dụng trống và lý do rất đơn giản: trống là hoạt động liên tục trong thời gian cho tất cả các vùng chứa chuẩn, nhưng đối với một số danh sách triển khai, kích thước mất thời gian tuyến tính.

.....

Không có vấn đề gì xảy ra, bạn không thể đi sai nếu bạn gọi trống thay vì kiểm tra để xem nếu size() == 0. Vì vậy, bất cứ khi nào gọi trống bạn cần biết liệu vùng chứa có yếu tố không.

+3

Không, 'size()' là tất cả nhưng được bảo đảm là O (1) , đặc biệt là cho 'vector'. Trong C++ 0x, 'size()' sẽ được yêu cầu là O (1) cho bất kỳ vùng chứa nào triển khai thực hiện nó. –

+0

@James: cho danh sách là tốt? – sbi

+1

@sbi: Yep; tất cả các thùng chứa. Hiện nay các yêu cầu về container chỉ nói rằng 'size()' _should_ có độ phức tạp về thời gian (có nghĩa là không có yêu cầu phức tạp nào cả). C++ 0x thay đổi điều đó. Tôi đã sai trong bình luận đầu tiên của tôi khi tôi nói "cho bất kỳ container thực hiện nó," mặc dù; tất cả các thùng chứa phải thực hiện 'size()'. –

8

Tôi sẽ nói là không có 2, vì phương thức empty() được thiết kế cố ý để kiểm tra xem một vectơ có trống không. Bạn cũng có thể kiểm tra hiệu quả của cả hai cách tiếp cận, và sau đó quyết định cái nào tốt hơn.

+4

Phương thức 'empty' đặc biệt tốt cho' std :: list's vì tính toán kích thước của chúng có thể rất dài. – Benoit

+1

@Benoit: Một số hiện thực của 'list' có một thời gian không đổi' size() '; trong C++ 0x, 'size()' sẽ được yêu cầu có độ phức tạp về thời gian liên tục cho tất cả các vùng chứa, bao gồm 'danh sách'. –

+0

@James: Đó là lý do chính đáng để sử dụng danh sách 'danh sách' của bên thứ ba hoặc tùy chỉnh, nếu bạn tình cờ sử dụng' splice' và muốn * đó * thành hằng số thay thế. Sau đó, nó trở lại để có 'my_list :: size' là O (N). – Potatoswatter

2

Nếu bạn chưa quen với lập trình, hãy sử dụng chương trình có ý nghĩa hơn với bạn. Ví dụ: nếu == 0 có ý nghĩa hơn với bạn .empty(), hãy dùng nó.

Sau đó, nếu bạn có vấn đề về hiệu suất (tôi nghi ngờ rằng bạn sẽ có ở đây) sử dụng một thỏa mãn mục tiêu hiệu suất của bạn.

+5

Tôi thích đồng nghiệp của tôi, người mới hay không, sử dụng một trong đó có ý nghĩa nhiều hơn cho các lập trình viên có kinh nghiệm. Tất cả chúng ta sẽ có kinh nghiệm tại một thời gian, sau khi tất cả. – sbi

+0

@sbi: Không chỉ vậy, mà là tốt hơn cho hiệu suất trong thời gian dài (ví dụ: nếu bạn chuyển từ 'std :: vector' sang' std :: list' trong tương lai). –

+0

@sbi: bạn có quan điểm của mình ở đó - tuy nhiên, mã khó đọc, bạn phải làm cho nó dễ dàng cho chính mình ở đây và bây giờ. –

30

v.size() == 0 nói "Tôi đang so sánh kích thước", nhưng làm như vậy để kiểm tra xem vùng chứa có trống không. Có một thuật toán nhỏ để tiêu hóa (rất nhỏ, vì nó chỉ bao gồm so sánh) trước khi bạn biết nó làm gì.
OTOH, v.empty() thực hiện chính xác những gì nó nói: nó kiểm tra xem v có trống không.
Do đó, tôi rõ ràng thích # 2, như nó làm những gì nó nói. Đó là lý do tại sao empty() được phát minh, sau khi tất cả.

Nhưng có cũng là một lý do thuật toán để thích empty(): Nếu ai đó sau thay đổi std::vector thành một std::list, v.size()sức có O (n). (Trong C++ 03 nó đảm bảo được O (1) cho std::vector, nhưng không phải cho std::list. Theo bình luận của James để Prasoon's answer nó sẽ là O (1) cho tất cả container trong C++ 1x.)

+1

Để trả lời câu hỏi/bình luận của bạn dưới đây, Howard Hinnant đã viết một bài báo thảo luận về sự cân bằng cho 'danh sách' (nó thực sự là một mối nối() - tốc độ so với kích thước() - tốc độ cân bằng). Tôi dường như không thể vào được tờ báo này ngay bây giờ, nhưng [Michael Burr tóm tắt nó.] (Http://stackoverflow.com/questions/228908/is-listsize-really-on/228914#228914). –

+0

@James: Cảm ơn! – sbi

+0

C++ 1x là gì? : - | – Donotalo

3

Thông thường, một vectơ được thực hiện bên trong như một con trỏ tới một mảng được phân bổ động, và các thành viên dữ liệu giữ các số capacitysize của vectơ. size của vectơ là số phần tử thực tế, trong khi dung lượng đề cập đến kích thước của mảng động.

Với việc triển khai này, chức năng thành viên size() sẽ chỉ đơn giản là trở thành thành viên của size.

empty() sẽ trả lại kết quả của so sánh size == 0.

Vì vậy, cả hai đều có hiệu quả như nhau O(1) nhưng được đề xuất là empty() nếu bạn muốn kiểm tra xem véc tơ có trống không. Bởi vì đó là chức năng của nó. Nó sẽ làm cho mã của bạn dễ đọc hơn.

-1

Đi cho trống().

+0

Tôi (dis) như lý do của bạn cho ý kiến ​​của bạn. – sbi

+1

Không nên có nhiều phiền toái về kích thước trống cho vector phải không? : D – nakiya

1

Just for fun: tại sao không:

if(Vector.begin() == Vector.end()) 

?

1

Thực ra vector.empty() và vector.size() == 0 đang thực hiện tương tự. trống so sánh bắt đầu và kết thúc và trả về true nếu chúng giống nhau, kích thước tính toán bắt đầu - kết thúc để trả về 0 nếu nó rỗng để làm điều tương tự bằng cách sử dụng phép tính khác.

+0

Xin lỗi, bạn có thể thuật lại câu trả lời của mình không? Thật khó hiểu, hãy thử tách các câu và nói rõ lý do tại sao một là giống như câu khác. – Armfoot

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