C++ איטרטורים וקטורים

C Ytrtwrym Wqtwrym



האיטרטורים העיקריים ב-C++ הם איטרטור קלט, איטרטור פלט, איטרטור קדימה, איטרטור דו-כיווני ואיטרטור גישה אקראית. איטרטור הפוך הוא לא באמת איטרטור; זה מתאם איטרטור. יש כמה גרסאות לאיטרטורים, כמו איטרטור קבוע.

איטרטור הוא מצביע משוכלל. כמו מצביע, הוא מצביע על אובייקטים מאותו סוג בזיכרון בזמנים שונים. כל האיטרטורים ניתנים להפניה, למעט איטרטור הפלט שניתן להפנות רק עבור קבוצה של טיפוסים. ניתן להרחיק פירושו שניתן להשיג את הערך שאליו מצביע המצביע או האיטרטור באמצעות אופרטור העקיפה, *. ניתן להוסיף מספר שלם לכמה איטרטורים באותו אופן, ולאותה מטרה, המספר השלם יתווסף למצביע.

השאלות למאמר זה הן: מהם האיטרטורים האלה? באילו מהאיטרטורים האלה נעשה שימוש עם וקטור C++? כיצד משתמשים באיטרטורים הללו עם וקטור C++? מאמר זה עונה על כל השאלות הללו בצורה פשוטה. בסוף מאמר זה, כאשר כל השאלות הללו היו נענות, איטרטורים וקטורים של C++ יהיו אינטואיטיביים וטבעיים (עבור הקורא).







תוכן המאמר

סיכום של C++ Iterators

איטרטור קלט



הרעיון של איטרטור קלט הוא שתוכנית תקבל ערך קלט. שלא כמו איטרטור הפלט, איטרטור הקלט תמיד ניתן לאיטרטור. עבור שני איטרטורי קלט, a ו-b, 'a == b' אינו מרמז על '++a == ++b'.



איטרטור פלט
הרעיון של איטרטור פלט הוא שתוכנית תשחרר ערך פלט. שלא כמו איטרטור הקלט, איטרטור הפלט לא תמיד ניתן להתייחסות. ניתן לא להתייחס אליו רק עבור קבוצה של סוגים.





איטרטור קדימה
האיטרטור קדימה יכול לסרוק את הווקטור מההתחלה ועד הסוף, בזה אחר זה (הגדלה). יש לו את כל הדרישות של איטרטור הקלט, בתוספת דרישות נוספות. זה יכול להחליף איטרטור קלט. עבור שני איטרטורים קדימה, a ו-b, 'a == b' מרמז על '++a == ++b'.

איטרטור דו כיווני
האיטרטור הדו-כיווני יכול לסרוק את הווקטור מההתחלה ועד הסוף, אחד אחד. מהסוף להתחלה, אחד אחד (בירידה). יש לו את כל הדרישות של האיטרטור קדימה, בתוספת דרישות נוספות. זה יכול להחליף איטרטור קדימה. עבור שני איטרטורים דו-כיווניים, a ו-b,



'a == b' מרמז על '++a == ++b'
ו
'–a == –b' מרמז על 'a == b'.

איטרטור גישה אקראית

האיטרטור של גישה אקראית כולל את כל הדרישות של האיטרטור הדו-כיווני, בתוספת דרישות נוספות. זה יכול להחליף איטרטור דו-כיווני. איטרטור הגישה האקראית מגיע עם היתרון שאם הוא מצביע כעת על האלמנט הראשון והאלמנט הרביעי נדרש, הוא ידלג על האלמנט השני והשלישי ויצביע על האלמנט הרביעי. הדילוג ההפוך כלפי מטה נכון.

איטרטור הפוך

שימו לב של-C++ אין איטרטור הפוך רגיל שכן יש לו איטרטור קדימה. אז יש מתאם שנקרא Reverse Iterator. יש עוד חדשות טובות: האיטרטור ההפוך עונה על כל הדרישות של איטרטור דו-כיווני.

איטרטור קבוע

אם אומרים על איטרטור שהוא קוסט איטרטור, לא ניתן לשנות את האלמנט שאליו הוא מצביע.

וקטור בנייה וגישה

מיכלים ב-C++ הם: מערך class, deque, forward_list, list, vector, map, set, unordered_map ו-unordered_set. הווקטור הוא מיכל. תבניות פונקציות מסוימות בספרייה הסטנדרטית של C++ פועלות עם איטרטורים באופן ישיר או עקיף. מיכלי C++, כמו גם הווקטור, משתמשים בפונקציות הללו. פונקציות אלה יכולות להיות זמינות לתוכנית C++ עם אחת מהוראות ההכללה הבאות:

#include

אוֹ

#include

הכללת כל אחד מהמכולות האחרות תאפשר גם תבניות פונקציות אלו. תבנית פונקציה מיועדת לפונקציה שיכולה לפעול עם סוגי נתונים שונים. הווקטור משתמש באיטרטורים דרך תבניות פונקציות אלו. חלק מתבניות הפונקציות והקשר שלהן לוקטור הם כדלקמן:

בְּנִיָה

פונקציית תבנית:

תבנית < מעמד ג > constexpr אוטומטי נתונים ( ג & ג ) - > decltype ( ג. נתונים ( ) ) ;

auto פירושו שסוג ההחזרה נקבע בהערכת הפונקציה. c הוא האובייקט של מחלקה C.

דוגמה לאובייקט וקטור שנבנה בצורה מרומזת היא:

וֶקטוֹר < לְהַשְׁחִיר > vtr ;

כאן האובייקט, c, ריק.

פונקציית תבנית:

תבנית < מעמד ו > constexpr const ו * נתונים ( initializer_list < ו > ה ) לא למעט ;

כאן, E* הוא איטרטור המצביע על האלמנט הראשון של הרשימה או המיכל. השימוש בו עם הווקטור באופן מרומז, יהיה עם:

וֶקטוֹר < לְהַשְׁחִיר > vtr { 'א' , 'ב' , 'ג' , 'ד' , 'ו' } ;
וֶקטוֹר < לְהַשְׁחִיר > :: const_iterator זה = vtr. התחל ( ) ;

פונקציית התבנית ישימה יותר למשפט ההתחלה () (המשפט השני).

גִישָׁה

פונקציית תבנית:

תבנית < מעמד ג > constexpr אוטומטי גודל ( const ג & ג ) - > decltype ( ג. גודל ( ) ) ;

זה מחזיר את גודל המיכל. דוגמה וקטורית:

וֶקטוֹר < לְהַשְׁחִיר > vtr { 'א' , 'ב' , 'ג' , 'ד' , 'ו' } ;
int נ = vtr. גודל ( ) ;
cout << נ << endl ;

הפלט הוא 5.

פונקציית תבנית:

תבנית < מעמד ו > [ [ nodiscard ] ] constexpr bool ריק ( initializer_list < ו > ה ) לא למעט ;

מחזירה true אם הרשימה ריקה או שקר אחרת. דוגמה וקטורית:

וֶקטוֹר < לְהַשְׁחִיר > vtr { 'א' , 'ב' , 'ג' , 'ד' , 'ו' } ;
bool עם = vtr. ריק ( ) ;
cout << עם << endl ;

הפלט הוא 0 עבור false.

גישה לטווח

ישנן פונקציות תבנית אחרות, המשתמשות באיטרטורים שהווקטור משתמש בהם לבעיות הטווח שלו. טווח הוא קבוצה רצופה של רכיבי מיכל.

פונקציית תבנית:

תבנית < מעמד ג > constexpr אוטומטי התחל ( ג & ג ) - > decltype ( ג. התחל ( ) ) ;

זה מחזיר איטרטור המצביע על האלמנט הראשון ברשימה. אוטומטי כאן פירושו, ערך ההחזרה נקבע בהערכה. דוגמה לוקטור:

וֶקטוֹר < לְהַשְׁחִיר > vtr { 'א' , 'ב' , 'ג' , 'ד' , 'ו' } ;
וֶקטוֹר < לְהַשְׁחִיר > :: איטרטור זה = vtr. התחל ( ) ;
cout << * זה << ' \n ' ;

הפלט הוא A. האיטרטור המוחזר כאן הוא איטרטור גישה אקראית. ניתן היה להחזיר איטרטור גישה אקראית קבוע - ראה מאוחר יותר.

תבנית פונקציה:

תבנית < מעמד ג > constexpr אוטומטי סוֹף ( const ג & ג ) - > decltype ( ג. סוֹף ( ) ) ;

מחזירה איטרטור קבוע המצביע על האלמנט האחרון ברשימה. קוד וקטור:

וֶקטוֹר < לְהַשְׁחִיר > vtr { 'א' , 'ב' , 'ג' , 'ד' , 'ו' } ;
וֶקטוֹר < לְהַשְׁחִיר > :: const_iterator זה = vtr. סוֹף ( ) ;
-- זה ;
cout << * זה << '' ;
-- זה ;
cout << * זה << endl ;

הפלט הוא 'E D'. ניתן להגדיל או להקטין איטרטור קבוע, אך לא ניתן לשנות את הערך שאליו הוא מצביע. ניתן היה להחזיר איטרטור גישה אקראית רגיל - ראה מאוחר יותר.

תבנית פונקציה:

תבנית < מעמד ו > constexpr reverse_iterator < const ו * > rbegin ( initializer_list < ו > ה ) ;

מחזירה את הערך האחרון ברשימה. rbegin() מצביע על האלמנט האחרון של הרשימה ולא מעבר לאלמנט האחרון של הרשימה, כמו end() עושה. דוגמה וקטורית:

וֶקטוֹר < לְהַשְׁחִיר > vtr { 'א' , 'ב' , 'ג' , 'ד' , 'ו' } ;
וֶקטוֹר < לְהַשְׁחִיר > :: reverse_iterator זה = vtr. rbegin ( ) ;
cout << * זה << '' ;
++ זה ;
cout << * זה << endl ;

הפלט הוא: E D. עם האיטרטור ההפוך, ++ יש השפעה הפוכה עבור האיטרטור הדו-כיווני.

תבנית פונקציה:

תבנית < מעמד ו > constexpr reverse_iterator < const ו * > עושה ( initializer_list < ו > ה ) ;

נקודות ממש לפני הרכיב הראשון ברשימה. דוגמה וקטורית:

וֶקטוֹר < לְהַשְׁחִיר > vtr { 'א' , 'ב' , 'ג' , 'ד' , 'ו' } ;
וֶקטוֹר < לְהַשְׁחִיר > :: reverse_iterator זה = vtr. עושה ( ) ;
-- זה ;
cout << * זה << '' ;
-- זה ;
cout << * זה << endl ;

הפלט הוא A B. עם האיטרטור ההפוך, - יש השפעה הפוכה עבור ++ של האיטרטור הדו-כיווני.

ישנן פונקציות נוספות של תבנית תחת כותרת זו - ראה מאוחר יותר.

הכנס איטרטורים

reverse_iterator הוא מתאם איטרטור, לא באמת איטרטור. איטרטור ההוספה הוא גם מתאם איטרטור. הוא עונה על כל הדרישות של איטרטור הפלט, בתוספת הדרישות שלו. הוא קיים בשלוש צורות ב-C++: ה-back_inserter, ה-front_inserter וה-inserter. לכל אחד מאלה יש בנאי משלו.

Back_inserter:

מוסיף מאחור!
אבות טיפוס חשובים:

מְפוֹרָשׁ back_insert_iterator ( מְכוֹלָה & איקס ) ;
back_insert_iterator & מַפעִיל = ( סוג שם מְכוֹלָה :: סוג_ערך && ערך ) ;

דוגמה וקטורית:
לוקטור אין שום פונקציית איבר הוספה הנכנסת מאחור. עם זאת, ניתן לראות את פונקציית החברים push_back(t) כך.

מכניס_חזית

מוסיף בחזית!
אבות טיפוס חשובים:

מְפוֹרָשׁ front_insert_iterator ( מְכוֹלָה & איקס ) ;
front_insert_iterator & מַפעִיל = ( סוג שם מְכוֹלָה :: סוג_ערך && ערך ) ;

דוגמה וקטורית:
לוקטור אין שום פונקציית איבר הוספה שמתווספת בחזית. לוקטור אין גם את פונקציית האיבר push_front(t).

החדשות הטובות הן שלווקטור יש פונקציות של Insert Member שיכולות להכניס בכל מקום, בתחילתו, בתוך או בסוף הווקטור.

מַתקֵעַ

איטרטור זה יוכנס בתחילת הווקטור, בתוך או בסופו.

אבות טיפוס חשובים:

insert_iterator ( מְכוֹלָה & איקס, סוג שם מְכוֹלָה :: איטרטור אני ) ;
insert_iterator & מַפעִיל = ( סוג שם מְכוֹלָה :: סוג_ערך && ערך ) ;

דוגמה וקטורית:

וֶקטוֹר < לְהַשְׁחִיר > vtr { 'א' , 'ב' , 'ג' , 'ד' , 'ו' } ;
וֶקטוֹר < לְהַשְׁחִיר > :: איטרטור זה = vtr. התחל ( ) ;
זה = זה + 2 ;
vtr. לְהַכנִיס ( זה, 'ג' ) ;

ל ( int אני = 0 ; אני < vtr. גודל ( ) ; אני ++ )
cout << vtr [ אני ] << ',' ;
cout << endl ;

הפלט הוא:

A, B, C, C, D, E,

ביטוי ההוספה הווקטורית הוא:

vtr. לְהַכנִיס ( זה, 'ג' ) ;

הוא מכניס את האלמנט ממש לפני המצביע (זה) שאליו הוא מצביע.

העבר איטרטור

ה-move_iterator הוא גם מתאם איטרטור. התוכנית הבאה דומה לדוגמא שנמצאת במפרט C++:

#include
#include <רשימה>
#include
באמצעות מרחב שמות סטד ;

int רָאשִׁי ( )
{
רשימה < לְהַשְׁחִיר > chs { 'א' , 'ב' , 'ג' , 'ד' , 'ו' } ;
וֶקטוֹר < לְהַשְׁחִיר > vtr ( make_move_iterator ( chs. התחל ( ) ) , make_move_iterator ( chs. סוֹף ( ) ) ) ;

cout << 'תוכן רשימה מקורית:' << endl ;
ל ( אוטומטי זה = chs. התחל ( ) ; זה ! = chs. סוֹף ( ) ; זה ++ )
cout << * זה << ',' ;
cout << endl << endl ;

cout << 'תוכן וקטור:' << endl ;
ל ( int אני = 0 ; אני < vtr. גודל ( ) ; אני ++ )
cout << vtr [ אני ] << ',' ;
cout << endl ;

לַחֲזוֹר 0 ;
}

הפלט הוא:

תוכן הרשימה המקורית:
אבגדה,

תוכן וקטור:
אבגדה,

איטרטור זה ממיר ערך מקור ל-rvalue לפני הצבתו ביעד.

סיכום

האיטרטורים העיקריים ב-C++ הם איטרטור קלט, איטרטור פלט, איטרטור קדימה, איטרטור דו-כיווני ואיטרטור גישה אקראית. לספרייה הסטנדרטית C++ יש כמה תבניות פונקציות המשתמשות באיטרטורים אלה. הווקטור משתמש באיטרטורים אלה דרך תבניות הפונקציות. לוקטור יש כמה שמות שונים עבור חלק מהאיטרטורים הללו. ישנם גם מתאמי איטרטור, שהם: reverse_iterator, מתאם איטרטור, ו-move_iterator. קיימות גם גרסאות מסוימות של איטרטורים. זה מספיק לכלול בתוכנית כדי לקבל את כל התכונות הללו. לאחר הבנת תפקידם של האיטרטורים, המתאמים ותבניות הפונקציות המשתמשות בהם, השימוש באיטרטורים עם וקטורים הופך לאינטואטיבי.