簡體   English   中英

C ++:使用&運算符傳遞引用

[英]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.

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