程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ Reference 的“三位一體”诠釋,reference三位一體

C++ Reference 的“三位一體”诠釋,reference三位一體

編輯:C++入門知識

C++ Reference 的“三位一體”诠釋,reference三位一體


C++ 是介於匯編語言與高級語言之間的一種“全能”語言。它的能力是其他任何基於VMA(馮-諾曼架構)計算機的高級程序設計語言無法望其項背的,而性能也只有C語言可與之伯仲。

 

然而長期以來,喜歡C++和憎恨C++的陣營,惡斗了三十多年,誰也說服不了誰。其中的一個重要原因是:C++的邏輯和語意難以分割,計算機學術界很難把它形式化(比如具有像Haskell那樣的數學美), 這和量子力學裡的不確定性類似,愛因斯坦就對此討厭之極。

 

這裡我不想評論兩方的對錯,但是我想就C++的一個最基本的概念,也是最重要的概念之一的“reference",作一番論述,看看是否說得通。

 

讀者如果讀過拙文“ http://blog.csdn.net/ly8838/article/details/38638491”,可能會對reference微妙的一面有所共鳴的。這裡我想進一步談談reference的一些細節。

 

要想敘述reference,我們不得不從更基本的定義 - 直接對象(direct object)說起.

C++中,直接對象是“常規變量”(normal variable), 具有“值語意”(value semantics),和rvalue 語意。 這還沒有引入reference,就已經陷入邏輯上“循環定義”的怪圈了。要想跳出,只有舉例:

 

long x;

MyClass m;  // MyClass is a user defined class

 

上面xm都是“直接變量”,它們在內存中的區域可以不同:可以在程序的靜態空間(全程變量),可以在工作堆棧內(自動變量),也可在動態空間內(間接地包含在母object中)。由於所在區域不同,這些直接變量對程序性能的特征影響很大(以後的博克會提及)。但是最重要的,是它們和傳統的“基本型變量(primitive type variable)”在語法用法上的相似。這是C++為何會支持它的重要原因。

 

對於首先學習C#,JavaScript, 或其他現代語言的程序員來說,“直接變量”幾乎沒有對應的概念。而更加令人不解的是,在“動態空間(heap)”中,直接變量只能“間接”地存在。而能夠“直接使用”動態變量"的唯一方法只有“指針”和“reference”. 這裡又陷入了循環:解釋直接變量時,又無法繞開“指針”和“reference”。

 

那麼reference到底是什麼呢?看看微基的解釋,(http://en.wikipedia.org/wiki/Reference_(C%2B%2B)),它幾乎也是同意反復,最後只有用“比喻”來解釋。也就是說,不用“指針”,“內存地址”等概念就無法解釋。

 

那麼,通俗上的說法“reference 是變量的alias (同體異名?)”是否說得通呢?

我認為,對於初學者來說,alias可謂最好的“比喻”。請看:

 

int x = int(10);           // line1

int & r = x;                // line2: r is an alias of x

r++;                         // line3: x is now 11

r = 3;                       // line4: x is now 3

assert (&r == &x);     // line5: r points to x

 

我們看到,上面的程序顯示,rx 幾乎沒任何區別,好像是形影相隨,難分難捨。這正是C++的宗旨:讓reference的變量和直接變量具有“等同”的語法,用法。

 

作為初級程序員來說,知道到這個用法也就夠了,但是“一點點知識是危險的”。如果我們以為xr 是一個東西,那就錯了:

 

首先,x 是“直接變量”,而r是間接變量,所以它們在語意上是完全不一樣的(編譯出來的代碼大相庭徑)。你可以說這與我無關,會應用就行了,這也不錯,不過並不能高枕無憂:在另一個環境裡,你可能就會因為不清楚object reference 和 direct object 的區別而出錯,或是寫出性能差別極大的程序。

 

從語意上看,line2 幾乎等於 r = &x (取x的地址),無怪乎許多人認為 reference 其實就是指針, 而且line5證明它的確指著它的“直接變量”。知道這一點,對於下列代碼很重要:

 

class X {…}

void myXFunction(X x) {…}

void myXFunction2(const X & x) {…}

 

如果認為X&X 的“alias”,而且用法一樣, 那麼你可能不需要myXFunction2,但是如果你知道X&的語意和X * 一樣,你才會推論出myXFunction2的性能一般會比myXFunction好,特別是當X裡面包含大量“成員”時,myXFunction2不用copy 內容,只需copy地址 (我們說這是淺拷貝- shallow copy), 而myXFunction必須傳入的內容copy argument變量中(我們說這是深拷貝- deep copy)。

 

在這裡,語意蓋過了邏輯。const X &x 的用法,特別是語意,最好用指針來诠釋才說得過去。

 

好吧,那就說reference是指針吧,可是它又不能解決上面程序line4的用法:

因為對一個指針賦值會使得它改變指向。若為指針,line4 會使得 指向地址為 的內存元,這和 alias 的概念又風馬牛不相及。

 

幸運的是實際情況並非如此:沒變(指向沒變),倒是 變了,在這個用例中,對 的 alias 诠釋從語法和語意上都雙雙勝過了指針诠釋。

 

綜上所述,reference 就像一個具有“波粒二象性”的光子, 它具有“pointer-alias” 二象性,不從語法-用法-語意的三方面理解,無法認識 reference 的真谛。

 

如果僅有二象也就罷了,OOP (C++ 支持OOP)有一個重要的概念,叫 polymorphism, 說的是一個“變量”其實可以是同時代表“基類”和其衍生類(derived  class):它既可以是A也可以是B(假設A是B的基類)(又是典型的量子悖論)。而這種 polymorphic 的變量,只能是指針和 reference,不可能是“直接變量”。這一特征又給 reference 加了另一頂帽子:polymorphic variable, 通俗說的話,它是具有同時擁有不同身份的“怪物”。這裡的詳情下次再談論。

 

為什麼polymorphic variable只能是指針reference呢?我個人認為,這無法用形式邏輯和常規邏輯來解釋,只能用指針的性質和C++ 的object model內存結構來解釋 - 這又是一個語意層面才能自圓其說的概念,是C++量子特性的另一佐證。以後我會用專文來诠釋C++這一重大問題。

 

總之,一個reference 的概念,包含了三種完全不同的诠釋,可以俗稱為三位一體

  • Alias (同體異名)
  • Pointer (指針)
  • Polymorphic variable (多身份變量)(我不喜歡多狀變量這一業界內常用的翻譯,認為它完全是概念混淆的,錯誤的,這裡沒有“狀態”,只有身份

 

到此可以做個總結,本文宗旨不是搬弄詞匯,而是企圖從邏輯,數學上诠釋C++的一些基本概念,以便拋磚引玉,喚起你對C++的深層思考。

此文的結論是:

 

1)C++的一些基本概念不是形式邏輯和傳統數學可以定義得清楚的。只有從“語意”上(編譯目標代碼)和“物理”上(計算機內存的結構)才能诠釋。

2)C++的語意(程序的硬件表達),是理解C++的關鍵。其他的語言,如Java,C#, JavaScript等,更接近數理邏輯,不用太在意其“語意”,95%的都能理解。

3)不懂C++語意,對C++程序員的深化和提高,寫出高質量,高性能的C++程序,有著不容忽略的負面影響。

 

楊鐮:2014-8-18 西雅圖


C/C++ Reference

hm格式文件下載: (好像是英文版的)其他的資料還有:
C~C++程序員實用大全(41.46M):
C++入門基礎教程(推薦 7.53M):
C/C++/C#程序員實用大全(精華版)(10.82M):
以上的我覺得都挺不錯,更多請自行網上搜索,推薦使用迅雷下載
另外,虛機團上產品團購,超級便宜
 

錯誤提示


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved