یک پیمایشگر (iterator) یک شیء (مانند یک اشارهگر) است که به یک عنصر درون نگهدارنده (container) اشاره میکند. میتوان از پیمایشگرها (iterators) برای انتقال کامل محتوای نگهدارنده استفاده کرد. آنها میتوانند به عنوان چیزی شبیه به یک اشارهگر که اشاره میکنند به تعدادی مکان تجسم شوند و میتوان با استفاده از آنها به محتوا در آن مکان خاص دسترسی داشت.
پیمایشگرها نقشی حیاتی در ارتباط الگوریتمها با نگهدارندهها همراه با دستکاری دادهی ذخیرهشده داخل نگهدارندهها بازی میکنند. واضحترین شکل یک پیمایشگر (iterator) یک اشارهگر (pointer) است. یک اشارهگر میتواند به عناصر در یک آرایه اشاره کند و میتوان تمام عناصر آرایه را با استفاده از اُپریتور افزایش (increment operator (++)) پیمایش کرد. اما همهی پیمایشگرها قابلیتی مشابه اشارهگرها را ندارند.
بسته به قابلیت پیمایشگرها آنها میتوانند به 5 دسته، طبقهبندی شوند. همانطور که در دیاگرام پایین نشان داده شده است، خارجیترین آنها، قدرتمندترین آنها است و در نتیجه درونیترین آنها کمترین قدرت را از نظر قابلیت دارند.
باید توجه داشت که هر کدام این پیمایشگرها توسط همهی نگهدارندهها در STL پشیبانیشده نیستند. تفاوت نگهدارندهها پشتیبانی از پیمایشگرهای مختلف است. مانند vector که از Random-access iterators پشتیبانی میکند، در حالی که lists از bidirectional iterators پشتیبانی میکند. لیست کامل در زیر ارائهشده است:
براساس قابلیت پیمایشگرها (iterators)، آنها میتوانند در 5 دستهبندی مهم طبقهبندی شوند:
آنها ضعیفترین همهی پیمایشگرها هستند و قابلیت بسیار محدودی دارند. آنها تنها میتوانند در یک الگوریتم single-pass استفاده شوند. به عنوان مثال، الگوریتمهایی که به ترتیب نگهدارنده را پردازش میکنند، به طوری که هیچ عنصری بیش از یکبار مورد دسترسی قرار نمیگیرد.
دقیقا مانند input iterators، آنها نیز در قابلیتشان بسیار محدود هستند و تنها میتوانند در الگوریتمها single-pass استفاده شوند. اما نه برای دسترسی به عناصر، بلکه برای عناصر اختصاص دادهشده.
آنها در سلسهمراتب نسبت به input و output iterators، بالاتر هستند و شامل همهی ویژگیها ارائه شده در این 2 پیمایشگر است. اما، همانطور که از نامش پیدا است، آنها نیز تنها میتوانند در یک جهت رو به جلو و همچنین یک گام در هر بار حرکت کنند.
آنها همهی ویژگیهای forward iterators همراه با این حقیقت که آنها مشکل forward iterators را حل کردهاند. به طوری که آنها میتوانند در هر دو جهت حرکت کنند. به همین خاطر است که نام آنها دوطرفه یا bidirectional است.
آنها قدرتمندترین پیمایشگرها هستند. آنها محدوده به حرکت پیدرپی نیستند. همانطور که از نامش مشخص است، آنها میتوانند به طور تصادفی به هر عنصر در داخل نگهدارنده دسترسی داشته باشند. آنها مواردی از قابلیتها هستند که شبیه به اشارهگرها هستند.
در دیاگرام زیر تفاوت در قابلیتهایشان با توجه به عملیاتهای متفاوتی که آنها میتوانند انجام دهند، نشان داده شده است:
مطمئنن راههای بسیار زیاد وجود دارد که نشان داد که پیمایشگرها بینهایت برای ما مفید هستند و ما را برای به شدت برای استفاده از آنها تشویق کند. برخی از مزایای استفاده از پیمایشگرها در زیر لیست شدهاند:
این بهتر است از پیمایشگرها برای پیمایش محتوای کامل نگهدارنده استفاده کنیم. مانند اینکه ما از یک پیمایشگر و دسترسی به عناصر با استفاده از اُپریتور [ ] استفاده نخواهیم کرد که بعد باید همیشه درمورد اندازهی نگهدارنده نگران باشیم. در حقیقت با پیمایشگرها میتوان به سادگی از تابع عضو ()end استفاده کرد و محتوای کامل را بدون نگه داشتن چیزی در ذهن، پیمایش کرد.
// C++ program to demonstrate iterators #include <iostream> #include <vector> using namespace std; int main() { // Declaring a vector vector<int> v = { 1, 2, 3 }; // Declaring an iterator vector<int>::iterator i; int j; cout << "Without iterators = "; // Accessing the elements without using iterators for (j = 0; j < 3; ++j) { cout << v[j] << " "; } cout << "\nWith iterators = "; // Accessing the elements using iterators for (i = v.begin(); i != v.end(); ++i) { cout << *i << " "; } // Adding one more element to vector v.push_back(4); cout << "\nWithout iterators = "; // Accessing the elements without using iterators for (j = 0; j < 4; ++j) { cout << v[j] << " "; } cout << "\nWith iterators = "; // Accessing the elements using iterators for (i = v.begin(); i != v.end(); ++i) { cout << *i << " "; } return 0; }
خروجی قطعهکُد بالا به این صورت است:
Without iterators = 1 2 3 With iterators = 1 2 3 Without iterators = 1 2 3 4 With iterators = 1 2 3 4
همانطور که در قطعهکُد بالا مشاهده کردید، بدون استفاده از پیمایشگرها، باید تعداد کل عناصر را در نگهدارنده، دنبال کنیم. در ابتدا تنها 3 عنصر وجود دارد، اما بعد 1 عنصر بیشتر به داخل آن وارد شده است. به این ترتیب حلقهی for هم باید اصلاح شود. اما با استفاده از پیمایشگرها، هر دو بار حلقه بدون اصلاح باقی میماند. بنابراین پیمایشگرها کار ما را راحتتر کردهاند.
حال در نظر بگیرید اگر v را یک لیست (list) به جای vector در برنامهی بالا تعریف کنیم، او اگر از پیمایشگرها برای دسترسی به عناصر استفاده نکنیم و تنها از اُپریتور [] استفاده کنیم، که در آن صورت این روش دسترسی برای لیست قابل استفاده نیست (همانطور که آنها از random-access iterators پشتیبانی نمیکنند). در این صورت، اگر از پیمایشگرها برای vector برای دسترسی به عناصر استفاده کنیم، تنها کافی است vector را به لیست در اعلامیهی پیمایشگر تغییر دهیم تا همان کار را انجام دهد، بدون انجام کاری دیگر. بنابراین پیمایشگرها از قابلیت استفادهی مجدد کُد پشتیبانی میکنند، به طوری که آنها میتوانند برای دسترسی به عناصر هر نگهدارنده استفاده شوند.
پیمایشگرها ما را قادر میسازند که هر زمان که بخواهیم، به راحتی، به طور پویا عناصر را به نگهدارنده حذف یا اضافه کنیم:
// C++ program to demonstrate iterators #include <iostream> #include <vector> using namespace std; int main() { // Declaring a vector vector<int> v = { 1, 2, 3 }; // Declaring an iterator vector<int>::iterator i; int j; // Inserting element using iterators for (i = v.begin(); i != v.end(); ++i) { if (i == v.begin()) { i = v.insert(i, 5); // inserting 5 at the beginning of v } } // v contains 5 1 2 3 // Deleting a element using iterators for (i = v.begin(); i != v.end(); ++i) { if (i == v.begin() + 1) { i = v.erase(i); // i now points to the element after the // deleted element } } // v contains 5 2 3 // Accessing the elements using iterators for (i = v.begin(); i != v.end(); ++i) { cout << *i << " "; } return 0; }
خروجی قطعهکُد بالا به این صورت است:
5 2 3
توضیح قطعهکُد بالا: همانطور که در قطعهکُد بالا مشاهده کردید، میتوان به راحتی و به طور پویا، عناصر را با استفاده از پیمایشگر به نگهدارنده اضافه یا حذف کرد، با این حال، انجام همین کار بدون استفاده از پیمایشگرها، میتواند بسیار خستهکننده باشد به طوری که لازم است عناصر را هر بار قبل از درجشدن و بعد از حذفشدن تغییر مکان داد.
منبع: وب سایت geeksforgeeks
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.