詳解C++編程中向函數傳遞援用參數的用法。本站提示廣大學習愛好者:(詳解C++編程中向函數傳遞援用參數的用法)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解C++編程中向函數傳遞援用參數的用法正文
援用類型的函數參數
向函數傳遞援用而非年夜型對象的效力平日更高。 這使編譯器可以或許在堅持已用於拜訪對象的語法的同時傳遞對象的地址。 請斟酌以下應用了 Date 構造的示例:
// reference_type_function_arguments.cpp
struct 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 = 7 y = 9
請留意,函數x 和 y 被聲明為前往援用類型。 這些函數可在賦值語句的每端上應用。
另請留意在 main 中,ThePoint 對象逗留在規模中,是以其援用成員仍處於運動狀況,可以平安地拜訪。
除以下情形以外,援用類型的聲明必需包括初始值設定項:
前往部分變量地址時的留意事項
假如在部分規模中聲明某個對象,則該對象會在函數前往時燒毀。 假如函數前往對該對象的援用,則當挪用方測驗考試應用 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 namespace
using 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 pointer
int 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。