函数通过引用返回变量? 在C++中,

函数通过引用返回变量? 在C++中,,c++,C++,如果函数通过引用返回变量,则该函数有效,对吗 有人能详细解释一下吗?先考虑一下这段代码 function() = 10; 看起来很像,不是吗?在本例中,函数返回指向int的指针,您可以通过对其应用一元*运算符以上述方式使用它 现在,在这个特定的上下文中,您可以将引用视为“伪装的指针”。也就是说,引用是一个“指针”,只是您不需要对其应用*运算符 int *function(); ... *function() = 10; 一般来说,将引用等同于指针不是一个很好的主意,但是对于这个特定的解释,它

如果函数通过引用返回变量,则该函数有效,对吗


有人能详细解释一下吗?

先考虑一下这段代码

function() = 10;
看起来很像,不是吗?在本例中,
函数
返回指向
int
的指针,您可以通过对其应用一元
*
运算符以上述方式使用它

现在,在这个特定的上下文中,您可以将引用视为“伪装的指针”。也就是说,引用是一个“指针”,只是您不需要对其应用
*
运算符

int *function();
...
*function() = 10;

一般来说,将引用等同于指针不是一个很好的主意,但是对于这个特定的解释,它工作得非常好。

考虑下面的代码,MyFunction返回指向int的指针,并将值设置为int

int &function();
...
function() = 10;
到目前为止你和我在一起吗

现在缩短到

int  *i;
i = MyFunction();
*i = 10;
它的作用与第一个代码块完全相同

您可以将引用视为始终取消引用的指针。因此,如果我的函数返回指向int的引用(而不是指针),则第一个代码块将变为

*(MyFunction()) = 10;
int  &i;
i = MyFunction();
i = 10;
第二个将成为

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

你还和我在一起吗?

通过一个小实验,你可以确定这是否有效

考虑到这个例子:

MyFunction() = 10;
它的输出是:

class foo {
    private:
        int _val;
    public:
        foo() { _val = 0; }
        int& get() { return _val; }
        void print() { printf("val: %d\n", _val); }
};

int main(void) {
    foo bar;
    bar.print();
    bar.get() = 10;
    bar.print();
}
因此,确实可以返回一个引用。请注意,被引用的变量可能超出范围,然后调用方可能会得到垃圾结果(就像取消引用指向已超出范围的对象的指针一样)。所以这很糟糕:

val: 0
val: 10

这个问题的答案与rvalue语义与lvalue语义有关。C++中的每个值都是左值或右值。左值是存储在可寻址内存位置中的值,这意味着它们是可赋值的(当然,假设它们是非常量)。右值基本上是其他任何内容,例如文字常量或不可寻址的临时值

因此,返回非常量引用的函数是左值。但是,按值返回的函数将是一个rvalue表达式,因为它返回一个不可寻址的临时值,因此不可赋值


请参阅该条目,以获得更详细的解释,并提供示例。

正如其他注释所示,函数可以返回对成员变量的引用,但需要注意的是:此函数不应是类接口的一部分。一旦提供了返回类内部引用的函数,就失去了对它们的控制。 如果你还没有读过“有效的C++”,那就去读吧。
书中第29项说“避免将句柄返回到内部数据”,并详细解释了为什么需要避免这种做法。

一个你没有问过的问题。
但你为什么要这么做

想想std::vector(我将原理扩展到方法)

这里有一个方法“operator[]()”,它重新调用对内部成员的引用。
这将允许以下操作:

int& get() {
    int myval = _val;
    return myval;
}
std::向量x(20,1);
x[5]=10;
//这相当于:
x、 运算符[](5)=10;
//这只是一个函数(方法)调用:
x、 函数(5)=10;

在返回参考资料时,请注意:无论返回的是什么,请注意其生命周期。这个例子很糟糕:

std::vector<int>  x(20,1);
x[5] = 10;

// This is quivalent to:
x.operator[](5) = 10;

// So this is just a function (method) call:
x.function(5) = 10;

x不存在于
函数
之外,也不存在对它的任何引用。为了从函数返回引用,被引用的对象必须至少与引用的持续时间相同。在上面的示例中,x需要声明为静态。其他可能的方法是将x设为全局变量,或将函数设为类成员函数并返回对类成员变量的引用,或在堆上分配x并返回对该变量的引用(尽管这在释放时很棘手)

+1以便在我之前进入。伟大的头脑和所有这些:)很好地使用了一个不太正确但仍然合适的类比来清楚地解释它,同时也指出了使用不太正确的类比的危险:)如何在不违反该规则的情况下重载运算符[]?弗雷德说得很好,但[](非常量)的语义表明运算符是变异的。通常如此使用,即x[5]=10;但是它当然可以被滥用,比如int&vectoreElement=x[5];(后来使用…哎哟…)但这是你为便利[]而付出的代价;如果
function()
按值返回用户定义类型的右值,它也可以工作-类似于
function().operator=(10)
,这是对非常量结构/类/联合右值的完全合法调用。@Pavel:甚至是常量值,一个think,假设您编写了一个const运算符=,我不明白为什么您只将其视为非const引用的特定内容。在这个特定的例子中,返回任何引用(const或not)都会导致相同的问题。嗯,是的,谢谢-今天有点间隔。我提到了non-const,因为您无论如何都不能修改const引用,但在我所说的其余内容的上下文中,这并不重要。