[英]C++: using & operator for pass-by-reference
我正在自學C ++,在這個過程中,我正在編寫簡單的小程序來學習基本思想。 關於“傳遞引用”,我很困惑為什么下面的代碼工作(一些代碼只是練習重載構造函數):
#include <iostream>
#include <string>
using namespace std;
class Dude
{
public:
string x;
Dude(); // Constructor 1
Dude(const string &a); // Constructor 2
};
Dude::Dude() : x("hi") {}
Dude::Dude(const string &a) : x(a) {}
int main()
{
Dude d1;
Dude d2 = Dude("bye");
cout << d1.x << endl;
cout << d2.x << endl;
return 0;
}
在“main()”中,我創建一個“Dude”類型的對象“d2”,並使用構造函數2將“x”設置為字符串“bye”。
但是在構造函數2的聲明中,我告訴它接受字符串的地址 ,而不是字符串本身。 那么為什么我可以傳遞它“bye”(這是一個字符串)。 為什么我不必創建變量字符串,然后將該字符串的地址傳遞給Dude的Constructor 2?
這實際上說明了C ++最酷和最有用的功能之一:臨時變量。 由於您指定了字符串引用是const
,因此編譯器允許您將對臨時值的引用傳遞給該函數。 所以,這就是Dude d2 = Dude("bye");
幕后發生的事情Dude d2 = Dude("bye");
:
Dude::Dude(const string &)
。 如何做出這個選擇是一個完全不同的主題。 string
值。 現在, "bye"
是一個const char[4]
但是編譯器可以平凡將其轉換成一個const char *
, 而且可以變成一個string
。 因此,創建了一個匿名臨時變量(稱為temp1
)。 "bye"
調用string::string(const char *)
,結果存儲在temp1
temp1
的引用調用Dude::Dude(const string&)
。 結果被分配給d2
(實際上,它被分配給另一個臨時變量, Dude
的復制構造函數被調用,帶有對它的const引用,並被分配給d2。但在這種情況下,結果是相同的。) temp1
被丟棄。 這是在temp1
上運行字符串析構函數string::~string()
我認為你誤解了&
運營商在這方面做了什么。 獲取變量( &var
)的地址不同於表示將參數作為引用傳遞(就像在const string &a
)。
你的代碼實際上在做的是隱式創建一個用字符串"bye"
初始化的新string
對象,然后通過引用傳遞給Dude
構造函數。 也就是說,您的代碼基本上是:
Dude d2 = Dude(string("bye"));
然后構造函數通過引用接收該字符串對象,並通過復制構造函數將其分配給x
。
在這種情況下, string
有一個構造函數,它接受一個const char*
並且沒有聲明為explicit
,因此編譯器將創建一個臨時string
(使用string("bye")
創建,前面提到的構造函數)然后你的const string&
設置為指那個臨時的。
兩件事情:
1)代碼中沒有“地址”這樣的東西。 const string&
表示“對string
常量引用 ”。
你可能會對這樣一個事實感到困惑:符號&
也用在完全不同的上下文中,作為創建指針的“address-of”運算符: T x; T * p = &x;
T x; T * p = &x;
。 但這與參考文獻無關。
2)你實際上並不一定要使用你聲稱為d2
的構造函數; 相反,您正在使用構造函數#2創建一個臨時對象,然后通過臨時構造函數構造d2
。 直接建築讀Dude d2("bye");
。
當您使用字符串參數調用第二個構造函數時,將創建一個引用該字符串副本的臨時變量並將其傳遞給構造函數。
構造函數2沒有將地址const string& a
字符串, const string& a
表示對std::string
對象的常量引用。 您可以將構造函數傳遞給字符串文字的原因是因為std::string
類包含一個帶有const char *
的非顯式構造const char *
。 因此,在調用Constructor 2之前,編譯器會先隱式將您的字符串文字轉換為std::string
。
所以以下兩行是等價的
Dude d2 = Dude("bye");
Dude d2 = Dude( std::string("bye") );
此外,在編寫構造函數時,更喜歡在初始化列表中而不是在構造函數體內初始化成員變量
Dude(const string &a) : x(a) {}
由於這個原因,temporaries可以綁定到const引用。
當你調用Dude("bye")
,編譯器會看到這是否是任何構造函數的完美匹配( char[4]
)。 不。 然后它檢查某些轉換( char*
)仍然沒有。 然后它檢查用戶轉換,並發現可以從char*
隱式構造std::string
所以它為你創建一個來自char*
的std::string
,並通過引用Dude
的構造函數傳遞它,復制。 在聲明結尾處Dude d2 = Dude("bye");
臨時字符串會自動銷毀。 如果我們必須為每個單個函數參數自己進行顯式轉換,那將會很煩人。
傳遞給引用參數的變量將自動傳遞其地址。 這很好,因為它允許我們處理具有值語義的對象。 我不必考慮傳遞一個字符串的實例,我可以傳遞它值 "bye"
。
構造函數#2接受對const string
的引用。 這允許它接受對預先存在的對象或臨時對象的引用(沒有const
限定符,不接受對臨時對象的引用)。
std::string
有一個構造函數,它接受一個指向char的指針。 編譯器使用它來創建一個臨時的std::string
對象,然后將對該臨時文件的引用傳遞給你的ctor。
請注意,編譯器將(隱式)為您執行這樣的一次轉換。 如果您需要多次轉換才能從源數據獲取目標類型,則需要明確指定其中一個轉換。
雖然“&”是地址運算符,但當在方法定義/聲明中聲明時,它意味着將引用傳遞給方法。 在這種情況下的參考是d2。 注意,D2不是指針,它是一個引用。 在構造函數中,“a”表示內容為“hi”的字符串對象。 這是C ++中方法的引用傳遞的典型示例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.