2008-12-17 9 views
6

Có cách nào để tôi có thể tìm thấy vùng chứa được chỉ bởi một trình lặp không? Cụ thể, tôi muốn có thể tìm thấy std :: vector được trỏ tới bởi một std :: vector :: iterator cụ thể để tôi có thể kiểm tra phạm vi, mà không cần phải thực sự chuyển các tham chiếu đến vectơ đó xung quanh.Tìm chủ sở hữu thiết bị lặp STL

Nếu (như tôi nghi ngờ) câu trả lời là không, tại sao không?

chỉnh sửa: cảm ơn một số câu trả lời chính xác và nhanh chóng (chủ yếu). Evan Teran làm móng tay. Tôi đã không suy nghĩ về tối ưu hóa ở tất cả, nhưng nó rõ ràng bây giờ.

Một vài người đã hỏi tôi muốn làm điều này. Không có gì quan trọng lắm. Tôi có một đối tượng được khởi tạo với một vectơ và một trình vòng lặp trỏ vào vectơ. Nó sẽ dễ thương và thuận tiện nếu tôi có thể khởi tạo đối tượng chỉ với một trình lặp, bởi vì sau đó tôi có thể chuyển đổi vector :: iterators trực tiếp đến đối tượng này (điều này nghe có vẻ kỳ lạ nhưng có ý nghĩa trong trường hợp cụ thể). Nhưng nó không quan trọng chút nào.

Trả lời

6

Tôi không tin như vậy. Nếu các trình vòng lặp phải giữ một tham chiếu/con trỏ tới chủ sở hữu, thì sẽ không thể tối ưu hóa chúng thành con trỏ trọng lượng nhẹ (có thể được thực hiện với các thùng chứa bảo đảm lưu trữ tiếp giáp như vectơ và như vậy).

0

Tôi không tin rằng có một phương pháp tiếp xúc để làm điều đó. Lý do là, đó không phải là mục đích của trình lặp. Có, tất nhiên, không có lý do kỹ thuật mà một iterator không thể giữ một con trỏ đến container cha của nó. Ngay cả khi nó được thực hiện theo cách mà không yêu cầu con trỏ đó, nó vẫn có thể giữ nó.

Iterator được thiết kế để lặp qua bộ sưu tập, và như vậy, chúng cung cấp giao diện cần thiết để thực hiện điều đó và chỉ điều đó. Đây là nguyên tắc lập trình hướng đối tượng tốt.

Tôi có thể hỏi trường hợp sử dụng của bạn là gì, bạn cần biết "phạm vi" của vùng chứa với trình lặp không?

3

Bạn không thể truy xuất vùng chứa từ trình lặp theo cách tổng quát. Ví dụ về lý do tại sao, một con trỏ đơn giản có thể được sử dụng làm trình lặp:

#include <algorithm> 
#include <cstdio> 
#include <cstring> 

int 
main(int argc, char *argv[]) 
{ 
     const char s[] = "Hello, world!"; 
     const char *begin = s; 
     const char *end = s + strlen(s); 

     std::for_each(begin, end, putchar); 

     return 0; 
} 

Làm cách nào bạn có thể truy xuất chuỗi gốc từ con trỏ (nếu nó không được chỉ vào đầu chuỗi)?

Tuy nhiên, nếu bạn cần chức năng này thì bạn luôn có thể implement trình bao bọc của riêng bạn quanh trình vòng lặp lưu trữ tham chiếu đến vùng chứa.

+0

Tôi không nghĩ rằng điều này thực sự liên quan đến câu hỏi đã được hỏi ... – jdmichal

+3

Nó chứng tỏ tại sao bạn không thể lấy container từ một lần lặp với một ví dụ cụ thể và đơn giản ... –

2

Về lý thuyết, có một cách nếu trình vòng lặp được đề cập ít nhất là trình lặp chuyển tiếp. Bạn có thể kiểm tra xem trình vòng lặp của bạn có phải là một trong các trình vòng lặp trong [đầu tiên, cuối cùng) cho mỗi vùng chứa ứng viên hay không. Vì bạn đang sử dụng một thùng chứa vector, bạn có một trình vòng lặp truy cập ngẫu nhiên, bạn có thể sử dụng toán tử nhỏ hơn để thực hiện việc kiểm tra này một cách nhanh chóng.

Bạn KHÔNG phải biết tất cả các vectơ ứng cử viên để kiểm tra trước, và đây không phải là cách tổng quát để có được vùng chứa mà một trình vòng lặp thuộc về.

Tuy nhiên, bạn có thể xác định phần mở rộng của trình vòng lặp truy cập ngẫu nhiên bằng cách trang trí trình vòng lặp truy cập ngẫu nhiên với thứ gì đó chứa con trỏ tới vectơ tạo. Điều này có khả năng hơi không phù hợp, không hiệu quả và bất tiện. Vì vậy, xem nếu bạn có thể viết lại mã để tránh điều này cần đầu tiên.

+1

Đề xuất đầu tiên này chắc chắn là dựa vào các chi tiết triển khai không có chi tiết và sẽ rất khó khăn để duy trì. Tôi sẽ thực hiện khá nhiều trang trí; ít nhất thì nó được đảm bảo luôn hoạt động và làm cho ý định của tôi hiển nhiên. – jdmichal

+0

Không đúng. Đề xuất đầu tiên dựa trên các trình vòng lặp kiểm tra bình đẳng khả năng, được hỗ trợ chính thức, hoặc khả năng

+0

Tôi muốn rút lại nhận xét trước đó của mình, nhưng tôi sẽ để lại nhận xét này cho hậu thế. Trên thực tế, giải pháp thực sự cần dựa vào các trình vòng lặp truy cập ngẫu nhiên về cơ bản được thực hiện như con trỏ hoặc một cái gì đó như con trỏ liên quan đến vị trí trong một không gian địa chỉ (theo định nghĩa kỹ thuật của "không gian địa chỉ"). Tôi không thấy một định nghĩa sạch, chuẩn hóa cho những gì xảy ra nếu bạn so sánh các trình vòng lặp truy cập ngẫu nhiên phát sinh từ các vùng chứa khác nhau. –

1

STL không cho phép điều này.Ví dụ:

Trình biến đổi Vecor có thể được thực hiện đơn giản như một con trỏ. Và không có cách nào chung để lấy một đối tượng từ một con trỏ trỏ tới một số dữ liệu mà đối tượng đã cấp phát.

0

Như đã đề xuất trước đó, tốt nhất là viết lại mã của bạn để bạn không cần hành vi này. Nó cũng giống như cầm một đồng xu, nhưng bạn không biết nó xuất phát từ đâu trừ khi bạn ghi lại điều đó trên một tờ giấy.

Nếu bạn không thể viết lại mã, bạn vẫn có thể giới thiệu một đối tượng bao gói chứa con trỏ đến vùng chứa và bản thân trình lặp. Bạn cần điều này để làm gì?

4

Không có cách nào để thực hiện công việc đó. Lý do rất đơn giản: Thêm cách vào các trình vòng lặp để nhận vùng chứa mà chúng đang trỏ đến là

  • Vô nghĩa. Iterator lặp qua bộ sưu tập. Như người khác nói, chỉ thế thôi, không gì hơn.
  • Không tương thích với các yêu cầu của trình lặp. Hãy nhớ rằng một con trỏ là một trình vòng lặp truy cập ngẫu nhiên. Đưa một con trỏ container vào trong trình vòng lặp sẽ không sử dụng cho các thuật toán, vì chúng có ý định chung chung, được tách riêng khỏi các triển khai trình lặp cụ thể. Một con trỏ được sử dụng như một trình lặp không thể có một con trỏ trở lại mảng mà nó được lấy từ một thành viên.

Bạn nói bạn cần nó để kiểm tra phạm vi. Bạn có thể cung cấp một trình lặp kết thúc, nó sẽ chỉ một điểm sau vị trí vòng lặp hợp lệ cuối cùng của một dãy. Kiểm tra xem vị trí hiện tại của bạn có ở vị trí cuối cùng không. Đó là tất cả những gì bạn cần làm để kiểm tra phạm vi.