簡體   English   中英

在 c++ 中通過引用返回

[英]Return by reference in c++

#include<iostream>
using namespace std;

int& add() {

    static int a;
    a++;
    cout<<"\na="<<a;
    return a;
}

int main {

   int x,y,m;
   int &z = add(); //it behaves as a reference to "a" which is a static variable
   x=add();//why does it work correctly
   y=add();//why does it work correctly
   z++;
   m=add();//why does it work correctly
   cout<<"\nx="<<x<<"\ny="<<y<<"\nz="<<z<<"\nm="<<m;
   return 0;
}

output:
a=1
a=2
a=3
a=5
x=2
y=3
z=5
m=5

x,y,m & z內部究竟發生了什么

int main{
    int x,y,m;      // declare three ints:  x,y,m, all unassigned
    int &z = add(); // a is incremented to 1, z is a reference to a
    x=add();        // add() returns a reference to a, x copies the value of a
    y=add();        // same as above
    z++;            // increments a, since z is a reference to a
    m=add();        // same as x and y, copies the value of a
    cout<<"\nx="<<x<<"\ny="<<y<<"\nz="<<z<<"\nm="<<m;
    return 0;
}

因此,您連續調用add()三次,這會將a遞增到 1、2、3(並每次都打印該值。

z是對真實a的引用。

xym是賦值時a的值的副本。 所以 x 是 2,y 是 3,我們通過z++跳過 4,然后 m 是 5。

int &z = add();

z是對 static 變量a的引用。 從現在開始, az是同義詞。 它們都指向相同的 memory 位置。

int x;
x = add();

x是一個獨立的 memory 位置。 由於賦值, x將保存add()在調用時返回的任何內容。 這也是ym的工作方式。

xym只是變量,因此它們在調用add時獲取a中的任何值,僅此而已。 如果您要更改任何這些變量的值,它不會影響a的值。 由於z是一個引用,因此它是指向 static a變量的“指針”(在某種意義上),因此更改z實際上會更改a

引用是某些 object 的另一個名稱、別名。 它的行為就像object。

add()返回對a的引用時,它的行為就像返回的值a

所以代碼

x = add();

表現得像以前一樣

a++;
x = a;

所以它捕捉到了a在那個時刻的價值。

另一方面,代碼

int& z = add();

表現得就像

a++;
int& z = a;

其中z成為a另一個名稱。 從現在開始使用az無關緊要,這意味着相同。 仍然只有一個值,但該值有兩個名稱。 我們可以使用其中任何一個來閱讀或更新它。

就像我們用 Bob 來指代一個叫 Robert 的人一樣——同一事物的另一個名字。

我相信這是它的工作原理:

在需要引用類型(的值)的上下文中使用的引用被隱式取消引用。 這包括(除其他外):

  • 賦值給變量
  • 通過值聲明的 function arguments
  • 傳遞 function 返回值聲明的值

在上述上下文中,創建了引用值的副本。

無論何時需要引用,它們都被視為引用(顯然沒有取消引用。)這包括:

  • 初始化兼容類型的引用
  • 通過引用聲明的 function arguments
  • 如果通過引用聲明,則傳遞 function 返回值

在這些上下文中,不會創建引用值的副本。 新引用只是現有值的新別名。

上述兩個上下文的語法是相同的,因此需要一些努力才能看到發生了什么。

引用只是一個常量指針,從某種意義上說,您可以更改指向的 object 但不能使其指向其他內容。

*所做的只是在您需要該值並允許使用. 而不是->來訪問指向的結構化類型的成員。

請注意,在 C++ 中有一個常見的反模式,它使用const X&就好像這比 function 參數的X更聰明。 請永遠不要忘記引用基本上是一個指針,因此指向的 object 在使用時可能會更改甚至消失( const並不意味着 object 不會更改,只是您無法使用該引用更改它)。

有關使用引用而不是值時應注意的原因的更詳細說明,請參閱此答案

每次您看到參考資料時,您都應該至少考慮一下 object 在您使用它時是否能夠存活和/或變異。 In your case the referenced object is a function static, therefore there are no problems with lifetime (function static objects come into existence the first time you enter the scope where they are defined and live until the end of the program).

將你的代碼翻譯成你得到的真正發生的事情(指針擺弄)

#include<iostream>
using namespace std;

int* add() {
    static int a;
    a++;
    cout << "\na=" << a;
    return &a; // we're returning a pointer to our static variable
}

int main(int argc, const char *argv[]) {
   int x,y,m;
   int *z = add(); // points to "a" which is a static variable
   x = *add();     // just get the current value of (incremented) a
   y = *add();     // same here, of course now different from x
   (*z)++;         // incrementing a from outside the function (we've a pointer!)
   m = *add();     // once again just reading current incremented value
   cout << "\nx=" << x << "\ny=" << y<< "\nz=" << (*z) << "\nm=" << m;
   return 0;
}

好,我們來剖析一下這個小程序

int& add() 
{
   static int a;
   a++;
   cout<<"\na="<<a;
   return a;
}

static int a 聲明一個變量。 Static 在這種情況下意味着只有一個地方可以存儲 a 並且每當調用 add 時都會使用該地方。 所以 a 就像一個全局變量,只能在 add 內部訪問。

返回值是一個引用。 大多數編譯器在內部使用指針來表示引用。 您可以在這里看到的是返回了對 static 變量 a 的引用。 一旦獲得參考,任何人都可以更改。

a++ 和 cout 很簡單——這里沒有進一步的評論。

int main{
    int x,y,m;      // declare three ints:  x,y,m, all unassigned
    int &z = add(); // a is incremented to 1, z is a reference to a
    x=add();        // add() returns a reference to a, x copies the value of a
    y=add();        // same as above
    z++;            // increments a, since z is a reference to a
    m=add();        // same as x and y, copies the value of a
    cout<<"\nx="<<x<<"\ny="<<y<<"\nz="<<z<<"\nm="<<m;
    return 0;
}

int &z = 添加(); 調用 add - 這意味着 a 遞增。 z 現在是 static 變量 a 的別名,因為它使用引用。 x=添加(); 再次增加 a 但現在復制 a 的值,因為 x 不是 int& 類型而是 int 類型。 y - 相同。 z++:因為 z 是 a 的別名 - 增加 a 而不通過 cout 打印它。

m=add():遞增 a,復制一個 int m,如 x 和 y。

output 一旦你理解了為什么 x,y,m 是副本而 z 是別名,就很簡單了。

任何問題仍然懸而未決?

問候

托拜厄斯

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM