2010-07-09 26 views
16

在C++中,什么是引用回报的意义?

function() = 10; 

作品如果函数通过引用返回的变量。

它有什么用途?

+3

尽管如此,没有必要使用该语法。你总是可以返回一个代理类对象,它的'operator ='在后台执行任务 – 2010-07-09 10:03:41

+1

这就是为什么我从来没有掌握C++的东西......你永远都不会停下来发现新的语法,这完全打击你的思想。得爱操作员重载:| – 2010-07-09 10:05:00

+0

您甚至可以按值返回并分配给临时。这就是为什么斯科特迈尔斯建议按常值返回的原因。 – Philipp 2010-07-09 10:07:59

回答

20

最常见的情况是实现诸如operator []之类的东西。

struct A { 
    int data[10]; 
    int & operator[](int i) { 
     return data[i]; 
    } 
}; 

另一种方法是通过一个accesor函数从一个类返回一个大对象:

struct b { 
    SomeBigThing big; 
    const SomeBigThing & MyBig() const { 
     return big; 
    } 
}; 

以避免复制的开销。

2

如果你有一个包含另一种结构的类,它可以直接修改包含结构有用:

struct S 
{ 
    int value; 
}; 

class C 
{ 
    public: 

     S& ref() { return m_s; } 

    private: 

     S m_s; 
}; 

让你写类似:

void foo() 
{ 
    C c; 

    // Now you can do that: 

    c.ref().value = 1; 
} 

注意:在这个例子中,直接公开m_s而不是返回引用可能更直接。

0

std::vectoroperator[]否则就不允许vec[n] = m

3

一个非常正常的用例是当你像类一样写一个数组时。在这里,你要重载operator []所以你可以做a[0] = 10;在这种情况下,你会想要签名要像int& operator[](int index);

4

getter/setter方法例如

class C 
{ 
    int some_param_; 
public: 
    int& param() { return some_param_; } 
    int const& param() const { return some_param_; } 
}; 

但在这里,你应该some_param是一个去public int。容器提供了通过引用返回的函数,例如。 vector<T>::operator[],以便您可以编写v[k] = x

+0

当您需要删除或替换另一个类型的对象的some_param_时,此实现很难重构。 – Basilevs 2010-07-09 10:15:16

2

SO搞砸了我的答案

你甚至都不需要返回一个参考:

struct C { }; 

C f() { 
    return C(); 
} 

int main() { 
    C a; 
    f() = a; // compiles fine 
} 

由于这种行为是相当惊人,你通常应该返回一个常量的值或常量除非用户有明智的意图修改结果。

2

实现存取

class Matrix 
{ 
    public: 
     //I skip constructor, destructor etc 

     int & operator()(int row, int col) 
     { 
     return m_arr[row + col * size]; 
     } 

    private: 
     int size; 
     int * m_arr; 
} 

Matrix m(10); 
m(1,0) = 10; //assign a value to row 1, col 0 
+0

我不知道为什么,但我讨厌矩阵类(我是一个数值分析师) – 2010-07-09 13:24:13

7

时,它可以是有用的考虑下面的代码,MyFunction的返回一个指针为int,并且将值设置为int。

int *i; 
i = MyFunction(); 
*i = 10; 

现在缩短,要

*(MyFunction()) = 10; 

它做同样的事情作为第一个代码块。

您可以将引用看作只是一个总是取消引用的指针。所以,如果我的函数返回的引用 - 不是指针 - 为int弗里斯特代码块将成为

int &i; 
i = MyFunction(); 
i = 10; 

和第二将成为

MyFunction() = 10; 

这就是我一直在寻找

+2

您发布的代码不合法​​C++ - 必须初始化引用。 – 2010-07-09 15:19:57

1

另一个经典案例:

class Foo { 
    Foo(); 
public: 
    static Foo& getSingleton(); 
}; 
0

你也可以实现方法链接(如果你愿意的话)u通过参考唱回来。

class A 
{ 
public: 
    A& method1() 
    { 
     //do something 
     return *this; //return ref to the current object 
    } 
    A& method2(int i); 
    A& method3(float f); //other bodies omitted for brevity 
}; 

int main() 
{ 
    A aObj; 
    aObj.method1().method2(5).method3(0.75); 

    //or use it like this, if you prefer 
    aObj.method1() 
     .method2(5) 
     .method3(0.75); 
} 
0

named parameter idiom是另一种用例。考虑

class Foo 
{ 
public: 
    Foo(
     int lions, 
     float tigers, 
     double bears, 
     std::string zookeeper 
    ); 
}; 

用户这个类的需要记住每个参数

Foo foo(1, 2.0, 5, "Fred"); 

它可以不看标题不明显的位置。相比于创造者类,像这样

class CreateFoo 
{ 
friend class Foo; 
public: 
    CreateFoo(); 

    CreateFoo& lions(int lions) { 
     _lions = lions; 
     return *this; 
    } 

    CreateFoo& tigers(float tigers) { 
     _tigers = tigers; 
     return *this; 
    } 

    CreateFoo& bears(double bears) { 
     _bears = bears; 
     return *this; 
    } 

    CreateFoo& zookeeper(const std::string& zookeeper) { 
     _zookeeper = zookeeper; 
     return *this; 
    } 

private: 
    int _lions; 
    float _tigers; 
    double _bears; 
    std::string _zookeeper; 
}; 

然后可以通过客户端,像这样

Foo foo = CreateFoo(). 
    lions(1). 
    tigers(2.0). 
    zookeeper("Fred"). 
    bears(5) 
    ; 

假设Foo有一个构造采取const CreateFoo&使用。