引用类型函数返回Reference-Type Function Returns

可将函数声明为返回引用类型。Functions can be declared to return a reference type. 做出此类声明有两个原因:There are two reasons to make such a declaration:

  • 返回的信息是一个返回引用比返回副本更有效的足够大的对象。The information being returned is a large enough object that returning a reference is more efficient than returning a copy.

  • 函数的类型必须为左值。The type of the function must be an l-value.

  • 引用的对象在函数返回时不会超出范围。The referred-to object will not go out of scope when the function returns.

就像它可能更有效,传递大型对象函数的引用,它也可以是返回大型对象更有效函数的引用。Just as it can be more efficient to pass large objects to functions by reference, it also can be more efficient to return large objects from functions by reference. 引用返回协议使得不必在返回前将对象复制到临时位置。Reference-return protocol eliminates the necessity of copying the object to a temporary location prior to returning.

当函数的计算结果必须为左值时,引用返回类型也可能很有用。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. 中介绍了重载运算符重载运算符Overloaded operators are covered in Overloaded Operators.

示例Example

请考虑 Point 示例:Consider the Point example:

// 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";
}

OutputOutput

x = 7
y = 9

请注意,函数xy 被声明为返回引用类型。Notice that the functions x and y are declared as returning reference types. 这些函数可在赋值语句的每一端上使用。These functions can be used on either side of an assignment statement.

另请注意在 main 中,ThePoint 对象停留在范围中,因此其引用成员仍处于活动状态,可以安全地访问。Note also that in main, ThePoint object remains in scope, and therefore its reference members are still alive and can be safely accessed.

除以下情况之外,引用类型的声明必须包含初始值设定项:Declarations of reference types must contain initializers except in the following cases:

  • 显式extern声明Explicit extern declaration

  • 类成员的声明Declaration of a class member

  • 类中的声明Declaration within a class

  • 函数的自变量或函数的返回类型的声明Declaration of an argument to a function or the return type for a function

返回局部变量地址时的注意事项Caution returning address of local

如果在局部范围中声明某个对象,则该对象会在函数返回时销毁。If you declare an object at local scope, that object will be destroyed when the function returns. 如果函数返回对该对象的引用,则当调用方尝试使用 null 引用时,该引用可能会在运行时导致访问冲突。If the function returns a reference to that object, that reference will probably cause an access violation at runtime if the caller attempts to use the null reference.

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

编译器会发出警告在此情况下: warning C4172: returning address of local variable or temporaryThe compiler issues a warning in this case: warning C4172: returning address of local variable or temporary. 在简单程序中,如果调用方在覆盖内存位置之前访问引用,则有时可能不会发生访问冲突。In simple programs it is possible that occasionally no access violation will occur if the reference is accessed by the caller before the memory location is overwritten. 这纯属运气。This is due to sheer luck. 请注意该警告。Heed the warning.

请参阅See also

参考资料References