יום ראשון

Reference Variables

והנה עוד אחד קטן יחסית, המדבר על מושג נוסף שקיים ב-c++ ולא קיים בשפת c.
Reference variable הוא מתן שם נוסף לאותו משתנה, כלומר alias.
הנה דוגמא להגדרת reference variable:

int a;
int & b = a;

משמעות הכתוב בשורה השניה: b הוא שם נוסף למשתנה a.
שימו לב - הסימון & יכול לשמש גם במשמעות של "כתובת של" למשל:

int *b;
int a;
b = &a;

אבל זו משמעות אחרת ואין קשר בין הדברים.
ה-reference variable יכול להיות מושם לכל data type - סטנדרטי, class וכו.
נסתכל על הפונקציה הבאה:


  1. void duplicate(int a){
  2. a = 2 * a;
  3. }
  4. int main(){
  5. int a = 2;
  6. duplicate(a);
  7. cout << a;
  8. }




main קוראת ל-duplicate עם הפרמטר a. בתוך duplicate מוכפל a פי 2. ערכו של a מודפס בשורה 7. הערך המודפס יהיה 2 ולא 4. למה? כי duplicate לא קיבלה את a אלא עותק שלו. כדי לשנות את a' היינו צריכים לשלוח pointer של a והפונקציה היתה נראית כך:


  1. void duplicate(int *a){
  2. *a = 2 * *a;
  3. }
  4. int main(){
  5. int a = 2;
  6. duplicate(&a);
  7. cout << a;
  8. }


כעת בשורה 7 יודפס 4, כי הערך של a אכן  הוכפל.
לגבי שורה 6: כאן משמעות ה-& היא "הכתובת של" ולא reference!

ה-reference variable הוא פתרון אקויולנטי לשימוש ב-pointer. בדומה ל-pointer יש לו שני יתרונות לעומת השימוש ב-direct variable:
1. ניתן לשנות את הערך של פרמטרים של פונקציה.
2. חוסך העתקות של המשתנים מהפונקציה ואליה. במקום זה, מועבר רק ה-reference מצד הפונקציה הקוראת. החיסכון יהיה כמובן משמעותי יותר כשמדובר בפרמטרים שהם אובייקטים גדולים.

הנה תוכנית המדגימה שימוש ב-reference variables:



  1. /*
  2.  * ref_var.cpp
  3.  *
  4.  *  Created on: Mar 18, 2012
  5.  *      Author: ronen halevy
  6.  */

  7. #include <iostream>
  8. using namespace std;

  9. class Example{
  10. private:

  11. public:
  12. void duplicate(int & par);
  13. };
  14. void Example::duplicate(int & par){
  15. par = 2 * par;
  16. }

  17. int main(void){
  18. int a;
  19. Example ex;
  20. a = 2;
  21. ex.duplicate(a);
  22. cout << " a = " << a << endl;
  23. }






בשורה 16מוגדרת המתודה duplicate. היא מקבלת virtual variable כפרמטר.
בשורה 18 ממומשת המתודה. היא מכפילה את הפרמטר שמקבל פי 2.
שימו לב לסימון & בשתי השורות הנ"ל.
כעת נפעיל את המתודה הנ"ל מתוך main.
שורה 26 שולחת את a שערכו 2 כפרמטר.
שורה 27 מדפיסה את a. תוצאת ההדפסה - 4.

שאלה: מה היה קורה אם main היתה נראית כך:


  1. int main(void){
  2. int a;
  3. Example ex;
  4. a = 2;
  5. ex.duplicate(a+5);
  6. cout << " a = " << a << endl;
  7. }
השינוי כאן הוא בשורה 5, שלא מכיל משתנה אלא ביטוי: a+5. במצב זה תתקבל הודעת שגיאה:
 no known conversion for argument 1 from ‘int’ to ‘int&’

ה-reference variable יכול להחליף רק משתנה ולא ביטוי.

למרות הנ"ל, אם ה-reference variable הוא מסוג const, הוא יכול להחליף גם ביטוי, אבל בתנאי שהמשתנה הוא מסוג constant, כך שלא ניתן לשנותו.

הנה דוגמא:
  1. /*
  2.  * ref_var.cpp
  3.  *
  4.  *  Created on: Mar 18, 2012
  5.  *      Author: ronen halevy
  6.  */

  7. #include <iostream>
  8. using namespace std;

  9. class Example{
  10. private:

  11. public:
  12. void duplicate(const int & par);
  13. };
  14. void  Example::duplicate(const int & par){
  15. int c = 2 * par;
  16. cout << " c = " << c << endl;
  17. }

  18. int main(void){
  19. int a;
  20. Example ex;
  21. a = 2;
  22. int c = ex.duplicate(a+2);
  23. cout << " a = " << a << endl;
  24. }

שורות 15 ו-17: שימו לב שה-reference variable הוא מסוג const. המשמעות: התוכנית לא תוכל לשנותו. 
שורה 26: המתודה duplicate מופעלת עם ביטוי ולא משתנה. אבל, היות שמדובר ב-constant, המערכת תייצר משתנה זמני שייצג את a+2. כש-duplicate תסתיים, המשתנה הזמני הזה יפסיק להתקיים.

=====

2 תגובות:

  1. היי, לא ממש הבנתי את היתרון הראשון של reference. הרי אני יכולה לשנות את המשתנים של הפונקציה ע"י pointer.תוכל להסביר לי את כוונתך?

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

      מחק