参照関数パラメータ、戻り値、およびポインタへの参照
9449 ワード
翻訳:https://docs.microsoft.com/en-us/cpp/cpp/reference-type-function-arguments?view=vs-2019
関数の参照タイプパラメータ
関数が返すオブジェクトは十分大きく、copyを返すよりも参照を返すほうが有効です. 関数タイプは左でなければならない、The type of the function must be an l-value. 呼び出し関数が戻ると、関数が返すオブジェクトは破棄されない(go out of scope) .
参照によって大きなオブジェクトを関数に渡すのと同様に、関数から大きなオブジェクトの参照を返すのも効率的です.関数からオブジェクトを返すリファレンスは、関数が戻る前にオブジェクトを一時的なメモリ位置にコピーする必要性を排除します.
関数が左の値とみなされる場合、参照タイプを返すオブジェクトも役立ちます.Reference-return types can also be useful when the function must evaluate to an l-value. Most overloaded operators fall into this category, particularly the assignment operator.
例:
出力:
注意:関数x yは参照タイプを返すように宣言されます.この2つの関数は、割り当てオペレータ=の左右に表示されます.
ただし、main関数ではThePointオブジェクトは破棄されていないため、メンバーは依然として存在し、安全にアクセスできます.
宣言参照タイプには、次の場合を除き、初期化器(initializer)が含まれている必要があります. explicit extern declaration クラスメンバーの宣言 は、クラスの内部に を宣言する.は、関数のパラメータとして宣言するか、関数の戻りタイプ である.
ローカル変数のアドレスを返すにはCaution returning address of localに注意してください。
関数の参照タイプパラメータ
通常、関数への参照の伝達は、伝達が大きいオブジェクトよりも効率的です.パスリファレンス関数を使用すると、コンパイラがオブジェクトのアドレスを関数に渡すと同時に、オブジェクトに直接アクセスするためのsyntax(オブジェクト名?)を保持できます.This allows the compiler to pass the address of the object while maintaining the syntax that would have been used to access the object. // reference_type_function_arguments.cpp
#include
struct Date
{
short Month;
short Day;
short Year;
};
// Create a date of the form DDDYYYY (day of year, year)
// from a Date.
long DateOfYear( Date& date )
{
static int cDaysInMonth[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
long dateOfYear = 0;
// Add in days for months already elapsed.
for ( int i = 0; i < date.Month - 1; ++i )
dateOfYear += cDaysInMonth[i];
// Add in days for this month.
dateOfYear += date.Day;
// Check for leap year.
if ( date.Month > 2 &&
(( date.Year % 100 != 0 || date.Year % 400 == 0 ) &&
date.Year % 4 == 0 ))
dateOfYear++;
// Add in year.
dateOfYear *= 10000;
dateOfYear += date.Year;
return dateOfYear;
}
int main()
{
Date date{ 8, 27, 2018 };
long dateOfYear = DateOfYear(date);
std::cout << dateOfYear << std::endl;
}
上記の例では、ポインタのメンバー選択オペレータではなく、参照によって渡される構造体オブジェクトのメンバーがメンバー選択演算子(.member-selection operator)によってアクセスされることを示しています->.
参照によって渡されるパラメータは、ポインタタイプ以外の構文に従いますが、constとして宣言されない限り、参照はポインタの重要な特性を保持します.上記の例では、入力パラメータは変更されていませんので、次のように変更します.long DateOfYear( const Date& date );
これにより、関数DateOfYearが入力したパラメータを変更しないことが保証されます.
Any function prototyped as taking a reference type can accept an object of the same type in its place because there is a standard conversion from typename to typename&.任意のパラメータが参照タイプの関数は、タイプからタイプへの標準変換があるため、同じタイプのオブジェクトを直接受け入れることができます(つまり、関数のパラメータが参照であれば、オブジェクトを直接渡すことができます).
関数は参照タイプを返します
関数は、2つの理由で1つの参照タイプを返すように宣言できます.
// reference_type_function_arguments.cpp
#include
struct Date
{
short Month;
short Day;
short Year;
};
// Create a date of the form DDDYYYY (day of year, year)
// from a Date.
long DateOfYear( Date& date )
{
static int cDaysInMonth[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
long dateOfYear = 0;
// Add in days for months already elapsed.
for ( int i = 0; i < date.Month - 1; ++i )
dateOfYear += cDaysInMonth[i];
// Add in days for this month.
dateOfYear += date.Day;
// Check for leap year.
if ( date.Month > 2 &&
(( date.Year % 100 != 0 || date.Year % 400 == 0 ) &&
date.Year % 4 == 0 ))
dateOfYear++;
// Add in year.
dateOfYear *= 10000;
dateOfYear += date.Year;
return dateOfYear;
}
int main()
{
Date date{ 8, 27, 2018 };
long dateOfYear = DateOfYear(date);
std::cout << dateOfYear << std::endl;
}
long DateOfYear( const Date& date );
関数は、2つの理由で1つの参照タイプを返すように宣言できます.
参照によって大きなオブジェクトを関数に渡すのと同様に、関数から大きなオブジェクトの参照を返すのも効率的です.関数からオブジェクトを返すリファレンスは、関数が戻る前にオブジェクトを一時的なメモリ位置にコピーする必要性を排除します.
関数が左の値とみなされる場合、参照タイプを返すオブジェクトも役立ちます.Reference-return types can also be useful when the function must evaluate to an l-value. Most overloaded operators fall into this category, particularly the assignment operator.
例:
// refType_function_returns.cpp
// compile with: /EHsc
#include
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() << "
"
<< "y = " << ThePoint.y() << "
";
}
出力:
x = 7
y = 9
注意:関数x yは参照タイプを返すように宣言されます.この2つの関数は、割り当てオペレータ=の左右に表示されます.
ただし、main関数ではThePointオブジェクトは破棄されていないため、メンバーは依然として存在し、安全にアクセスできます.
宣言参照タイプには、次の場合を除き、初期化器(initializer)が含まれている必要があります.
ローカル変数のアドレスを返すにはCaution returning address of localに注意してください。
ローカル範囲内のオブジェクトを宣言すると、関数が戻ってくるとオブジェクトが破棄されます.関数がオブジェクトへの参照を返す場合、この参照を使用すると、実行時のアクセス競合(an access violation at runtime)が発生する可能性があります.// C4172 means Don’t do this!!!
Foo& GetFoo()
{
Foo f;
...
return f;
} // f is destroyed here
コンパイラは警告を表示します:warning C4172: returning address of local variable or temporary
.単純なプログラムではこのようなエラーは容易に発見できますが、プログラムコードが増えるにつれてこのようなエラーはデバッグしにくく、使用時に注意してください.
ポインタへの参照
todo
// C4172 means Don’t do this!!!
Foo& GetFoo()
{
Foo f;
...
return f;
} // f is destroyed here
todo