引用用于函数参数,返回值,及指向指针的引用

Posted zyk1113

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了引用用于函数参数,返回值,及指向指针的引用相关的知识,希望对你有一定的参考价值。

本文翻译自: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 <iostream>

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&.任何参数是引用类型的函数可以直接接受一个同类型的对象,因为存在从类型到类型引用的标准转换(也就是说:如果一个函数的参数是引用,你可以将一个对象直接传递给它)。

函数返回引用类型

   函数可以被声明为返回一个引用类型,有两个原因这样做:

  • 函数返回的对象足够大,返回引用比返回一个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 <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() << "
"
<< "y = " << ThePoint.y() << "
";
}

输出:

x = 7
y = 9

  注意:函数x y被声明为返回引用类型。这两个函数可以出现在赋值操作符=的左右两侧。

  注意,在main函数中,ThePoint对象没有被销毁(remains in scope),因此它的成员仍然有且且可以安全的访问。

  声明引用类型必须包含初始化器(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

 

以上是关于引用用于函数参数,返回值,及指向指针的引用的主要内容,如果未能解决你的问题,请参考以下文章

指针和引用用于函数值传递

go语言中new与make的使用和区别

C++ 把引用作为函数返回值

右值引用,移动语义,完美转发

指针和引用函数指针

end — 将数组的内部指针指向最后一个单元