国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

詳解C++編程中向函數傳遞引用參數的用法

2020-05-23 14:09:13
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了詳解C++編程中向函數傳遞引用參數的用法,包括使函數返回引用類型以及對指針的引用,需要的朋友可以參考下
 

引用類型的函數參數
向函數傳遞引用而非大型對象的效率通常更高。 這使編譯器能夠在保持已用于訪問對象的語法的同時傳遞對象的地址。 請考慮以下使用了 Date 結構的示例:

// reference_type_function_arguments.cppstruct Date{short DayOfWeek;short Month;short Day;short Year;};// Create a Julian date of the form DDDYYYY// from a Gregorian date.long JulianFromGregorian( Date& GDate ){static int cDaysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31  };long JDate = 0;// Add in days for months already elapsed.for ( int i = 0; i < GDate.Month - 1; ++i )JDate += cDaysInMonth[i];// Add in days for this month.JDate += GDate.Day;// Check for leap year.if ( GDate.Year % 100 != 0 && GDate.Year % 4 == 0 )JDate++;// Add in year.JDate *= 10000;JDate += GDate.Year;return JDate;}int main(){}

前面的代碼顯示通過引用傳遞的結構的成員是通過成員選擇運算符 (.) 訪問的,而不是通過指針成員選擇運算符 (–>) 訪問的。
盡管作為引用類型傳遞的參數遵循了非指針類型的語法,但它們仍然保留了指針類型的一個重要特征:除非被聲明為 const,否則它們是可以修改的。 由于上述代碼的目的不是修改對象 GDate,因此更合適的函數原型是:

long JulianFromGregorian( const Date& GDate );

此原型將確保函數 JulianFromGregorian 不會更改其參數。
任何其原型采用引用類型的函數都能接受其所在位置的相同類型的對象,因為存在從 typename 到 typename& 的標準轉換。

引用類型函數返回
可將函數聲明為返回引用類型。 做出此類聲明原因有:

  • 返回的信息是一個返回引用比返回副本更有效的足夠大的對象。
  • 函數的類型必須為左值。
  • 引用的對象在函數返回時不會超出范圍。

就像通過引用傳遞大型對象 to 函數或返回大型對象 from 函數可能更有效。 引用返回協議使得不必在返回前將對象復制到臨時位置。

當函數的計算結果必須為左值時,引用返回類型也可能很有用。 大多數重載運算符屬于此類別,尤其是賦值運算符。 重載運算符在重載運算符中有述。
示例
請考慮 Point 示例:

// refType_function_returns.cpp// compile with: /EHsc#include <iostream>using namespace std;class Point{public:// Define "accessor" functions as// reference types.unsigned& x();unsigned& y();private:// Note that these are declared at class scope:unsigned obj_x; unsigned obj_y; };unsigned& Point :: x(){return obj_x;}unsigned& Point :: y(){return obj_y;}int main(){Point ThePoint;// Use x() and y() as l-values.ThePoint.x() = 7;ThePoint.y() = 9;// Use x() and y() as r-values.cout << "x = " << ThePoint.x() << "/n"<< "y = " << ThePoint.y() << "/n";}

輸出

 x = 7y = 9

請注意,函數x 和 y 被聲明為返回引用類型。 這些函數可在賦值語句的每一端上使用。
另請注意在 main 中,ThePoint 對象停留在范圍中,因此其引用成員仍處于活動狀態,可以安全地訪問。
除以下情況之外,引用類型的聲明必須包含初始值設定項:

  • 顯式 extern 聲明
  • 類成員的聲明
  • 類中的聲明
  • 函數的參數或函數的返回類型的聲明

返回局部變量地址時的注意事項

如果在局部范圍中聲明某個對象,則該對象會在函數返回時銷毀。 如果函數返回對該對象的引用,則當調用方嘗試使用 null 引用時,該引用可能會在運行時導致訪問沖突。

// C4172 means Don't do this!!!Foo& GetFoo(){  Foo f;  ...  return f;} // f is destroyed here

編譯器會在這種情況下發出警告:警告 C4172: 返回局部變量或臨時變量的地址。 在簡單程序中,如果調用方在覆蓋內存位置之前訪問引用,則有時可能不會發生訪問沖突。 這純屬運氣。 請注意該警告。

對指針的引用
聲明對指針的引用的方式與聲明對對象的引用差不多。聲明對指針的引用將生成一個可像常規指針一樣使用的可修改值。
以下代碼示例演示了使用指向指針的指針與使用對指針的引用之間的差異。
函數 Add1 和 Add2 在功能上是等效的(雖然它們的調用方式不同)。二者的差異在于,Add1 使用雙間接尋址,而 Add2 利用了對指針的引用的便利性。

// references_to_pointers.cpp// compile with: /EHsc#include <iostream>#include <string>// STL namespaceusing namespace std;enum {  sizeOfBuffer = 132};// Define a binary tree structure.struct BTree {  char *szText;  BTree *Left;  BTree *Right;};// Define a pointer to the root of the tree.BTree *btRoot = 0;int Add1( BTree **Root, char *szToAdd );int Add2( BTree*& Root, char *szToAdd );void PrintTree( BTree* btRoot );int main( int argc, char *argv[] ) {  // Usage message  if( argc < 2 ) {   cerr << "Usage: Refptr [1 | 2]" << "/n";   cerr << "/nwhere:/n";   cerr << "1 uses double indirection/n";   cerr << "2 uses a reference to a pointer./n";   cerr << "/nInput is from stdin./n";   return 1;  }  char *szBuf = new char[sizeOfBuffer];  if (szBuf == NULL) {   cerr << "Out of memory!/n";   return -1;  }  // Read a text file from the standard input device and  // build a binary tree.  //while( !cin.eof() )   {   cin.get( szBuf, sizeOfBuffer, '/n' );   cin.get();   if ( strlen( szBuf ) ) {     switch ( *argv[1] ) {      // Method 1: Use double indirection.      case '1':        Add1( &btRoot, szBuf );        break;      // Method 2: Use reference to a pointer.      case '2':        Add2( btRoot, szBuf );        break;      default:        cerr << "Illegal value '"         << *argv[1]         << "' supplied for add method./n"           << "Choose 1 or 2./n";        return -1;     }   }  }  // Display the sorted list.  PrintTree( btRoot );}// PrintTree: Display the binary tree in order.void PrintTree( BTree* MybtRoot ) {  // Traverse the left branch of the tree recursively.  if ( btRoot->Left )   PrintTree( btRoot->Left );  // Print the current node.  cout << btRoot->szText << "/n";  // Traverse the right branch of the tree recursively.  if ( btRoot->Right )   PrintTree( btRoot->Right );}// Add1: Add a node to the binary tree.//    Uses double indirection.int Add1( BTree **Root, char *szToAdd ) {  if ( (*Root) == 0 ) {   (*Root) = new BTree;   (*Root)->Left = 0;   (*Root)->Right = 0;   (*Root)->szText = new char[strlen( szToAdd ) + 1];   strcpy_s((*Root)->szText, (strlen( szToAdd ) + 1), szToAdd );   return 1;  }  else {   if ( strcmp( (*Root)->szText, szToAdd ) > 0 )     return Add1( &((*Root)->Left), szToAdd );   else     return Add1( &((*Root)->Right), szToAdd );  }}// Add2: Add a node to the binary tree.//    Uses reference to pointerint Add2( BTree*& Root, char *szToAdd ) {  if ( Root == 0 ) {   Root = new BTree;   Root->Left = 0;   Root->Right = 0;   Root->szText = new char[strlen( szToAdd ) + 1];   strcpy_s( Root->szText, (strlen( szToAdd ) + 1), szToAdd );   return 1;  }  else {   if ( strcmp( Root->szText, szToAdd ) > 0 )     return Add2( Root->Left, szToAdd );   else     return Add2( Root->Right, szToAdd );  }}

用法:Refptr [1 | 2]

其中:
1 使用雙間接尋址
2 使用對指針的引用。輸入來自 stdin。



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 清苑县| 扎赉特旗| 诏安县| 湖北省| 金堂县| 江西省| 北碚区| 福建省| 容城县| 措美县| 澄城县| 三明市| 库伦旗| 韩城市| 井陉县| 巴林左旗| 邓州市| 贵阳市| 晴隆县| 潍坊市| 西青区| 赤壁市| 康定县| 蓝山县| 小金县| 白玉县| 凉城县| 河曲县| 石阡县| 乌兰县| 罗江县| 涪陵区| 龙井市| 景宁| 西盟| 县级市| 厦门市| 垫江县| 西安市| 云浮市| 蒙阴县|