2012-07-12 3 views
9

Ví dụ, sau đây là có thể:Nhận con trỏ tới vùng chứa STL mà trình vòng lặp đang tham chiếu?

std::set<int> s; 
std::set<int>::iterator it = s.begin(); 

Tôi tự hỏi nếu điều ngược lại là có thể, ví dụ,

std::set<int>* pSet = it->**getContainer**(); // something like this... 
+0

Tôi muốn biết lý do bạn muốn điều này. – chris

+0

Điều tôi đang cố gắng làm là lưu trạng thái của trình lặp trong một số quá trình truyền tải (của một số cấu trúc dữ liệu khác) để tôi có thể tăng trình vòng lặp trong lần truy cập tiếp theo. Nếu ở trên là có thể thì tôi không phải giữ tham chiếu/con trỏ tới chính vùng chứa đó mà chỉ là con trỏ tới trình lặp đó. –

Trả lời

13

Không, không có cách nào di động để làm điều này.

Trình lặp có thể thậm chí không có tham chiếu đến vùng chứa. Ví dụ: triển khai có thể sử dụng T* làm loại iterator cho cả hai std::array<T, N>std::vector<T>, vì cả hai lưu trữ phần tử của chúng dưới dạng mảng. Ngoài ra, các trình vòng lặp tổng quát hơn nhiều so với các thùng chứa, và không phải tất cả các trình vòng lặp đều trỏ vào các thùng chứa (ví dụ, có các trình lặp đầu vào và đầu ra đọc và ghi từ các luồng).

+0

Đây là cũ nhưng tôi có một câu hỏi rất nhỏ. Giả sử rằng một iterator (không nhất thiết phải từ STL) đã bắt nguồn từ một container, nó có thể hoặc có thể không có một con trỏ/tham chiếu đến containter có nguồn gốc của nó. Nhưng nếu có, thì loại thùng chứa và chính vùng chứa, hoàn toàn được biết đến với người dùng của trình lặp, phải không? Trừ khi con trỏ/tham chiếu đến vùng chứa được định nghĩa là riêng tư, tất nhiên, nhưng tại sao lập trình viên muốn ẩn điều này? – Mark

5

No. Bạn phải nhớ vùng chứa mà trình lặp đến từ thời điểm bạn tìm thấy trình lặp. Một lý do có thể cho sự hạn chế này là con trỏ có nghĩa là các trình vòng lặp hợp lệ và không có cách nào để hỏi con trỏ tìm ra nó xuất phát từ đâu (ví dụ: nếu bạn chỉ 4 phần tử thành một mảng, cách con trỏ đó một mình như thế nào?). bạn có thể cho biết nơi bắt đầu của mảng không?).

2

Có thể có ít nhất một trong các trình biến đổi std và một số thủ thuật. std::back_insert_iterator cần một con trỏ đến vùng chứa để gọi phương thức push_back của nó. Hơn nữa con trỏ này chỉ là protected.

#include <iterator> 

template <typename Container> 
struct get_a_pointer_iterator : std::back_insert_iterator<Container> { 
    typedef std::back_insert_iterator<Container> base; 
    get_a_pointer_iterator(Container& c) : base(c) {} 
    Container* getPointer(){ return base::container;} 
}; 

#include <iostream> 
int main() { 
    std::vector<int> x{1}; 
    auto p = get_a_pointer_iterator<std::vector<int>>(x); 
    std::cout << (*p.getPointer()).at(0); 
} 

Đây là khóa học không sử dụng thiết thực, nhưng chỉ đơn thuần là một ví dụ về một iterator std rằng thực sự mang một con trỏ đến thùng chứa của nó, mặc dù một trong khá đặc biệt (ví dụ. Incrementing một std::back_insert_iterator là một noop). Toàn bộ điểm của việc sử dụng các trình vòng lặp không phải là để biết các phần tử đến từ đâu. Mặt khác, nếu bạn muốn một trình lặp cho phép bạn có được một con trỏ đến vùng chứa, bạn có thể viết một cái.