参照関数パラメータ、戻り値、およびポインタへの参照

9449 ワード

翻訳:https://docs.microsoft.com/en-us/cpp/cpp/reference-type-function-arguments?view=vs-2019

関数の参照タイプパラメータ


通常、関数への参照の伝達は、伝達が大きいオブジェクトよりも効率的です.パスリファレンス関数を使用すると、コンパイラがオブジェクトのアドレスを関数に渡すと同時に、オブジェクトに直接アクセスするための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つの参照タイプを返すように宣言できます.
  • 関数が返すオブジェクトは十分大きく、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.
    例:
    // 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)が含まれている必要があります.
  • explicit extern declaration
  • クラスメンバーの宣言
  • は、クラスの内部に
  • を宣言する.
  • は、関数のパラメータとして宣言するか、関数の戻りタイプ
  • である.

    ローカル変数のアドレスを返すには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