Trước tiên, lưu ý rằng trong trường hợp này, bạn không cần sử dụng bất cứ nhu cầu nào thực sự cần sử dụng std::copy
. Bạn chỉ có thể khởi tạo vectơ trực tiếp từ các trình vòng lặp:
vector<string> col((istream_iterator<string>(cin)),
istream_iterator<string>());
Điều này có thể không làm cho mã dễ hiểu hơn nhiều.
Theo như cách mã hoạt động, nó có thể hơi căng thẳng hơn bạn tưởng.Một istream_iterator trông mơ hồ như thế này:
template <class T>
class istream_iterator {
std::istream *is;
T data;
public:
istream_iterator(std::istream &is) : is(&is) { ++(*this); }
istream_iterator() : is(nullptr) {}
T operator++() { (*is) >> data; return *this; }
T operator++(int) { (*is) >> data; return *this; }
T const &operator*() { return data; }
bool operator !=(istream_iterator &end) { return (*is).good(); }
bool operator ==(istream_iterator &end) { return !(*is).good(); }
};
Rõ ràng là có nhiều hơn tôi bỏ qua, nhưng đó là hầu hết những gì chúng tôi quan tâm ở đây. Vì vậy, điều xảy ra là khi bạn tạo trình lặp, nó đọc (hoặc cố gắng) một mục từ luồng vào biến tôi đã gọi là data
. Khi bạn dereference iterator, nó trả về data
. Khi bạn tăng bộ lặp, nó đọc (hoặc cố gắng) mục tiếp theo từ tệp. Mặc dù được viết như thể họ so sánh một trình lặp với một trình lặp khác, operator==
và operator!=
thực sự chỉ kiểm tra phần cuối của tệp .
Đó là sau đó được sử dụng bởi std::copy
, mà (một lần nữa đơn giản hóa) trông hao hao như thế này:
template <class InIt, class OutIt>
void std::copy(InIt b, InIt e, OutIt d) {
while (b != e) {
*d = *b;
++b;
++d;
}
}
Vì vậy, đây đọc và mục từ iterator đầu vào, viết mục đó vào iterator đầu ra, và lặp đi lặp lại cho đến khi iterator cho vị trí hiện tại so sánh với iterator cho phần cuối của đầu vào (điều này sẽ xảy ra khi bạn đến cuối tập tin). Lưu ý rằng không giống như các trình vòng lặp khác, vị trí "kết thúc" duy nhất mà bạn được phép sử dụng với trình lặp istream là phần cuối của tệp.
- Lưu ý rằng về mặt kỹ thuật, đây không phải là hành vi phù hợp. Tôi đã so sánh đơn giản để giữ mọi thứ đơn giản. Hai trình lặp lặp mặc định được xây dựng nên so sánh bằng nhau và nếu bạn xây dựng hai trình lặp từ cùng một luồng, chúng nên so sánh bằng ít nhất trước khi bạn đọc bất kỳ thứ gì từ luồng. Điều này làm cho sự khác biệt thực tế ít mặc dù - so sánh duy nhất bạn nhìn thấy trong sử dụng thực tế là để xác định xem bạn đã đạt đến cuối tập tin chưa.
bạn nên đọc cuốn sách "The C++ STL" –