来自C#背景,我或多或少地对在C ++中返回方法处理这种看似奇怪的行为感到困惑。我现在关心的是C ++中的方法,通过引用返回并不是一个非常有用的技术,这是因为 - 与C#不同 - 一旦控件退出方法,任何在方法体内声明的变量都将超出范围。 / p>
因此,在C ++中,this甚至无法编译(但C#中的等效版本可以):
int& DoubleValue(int nX)
{
int nValue = nX * 2;
return nValue; // return a reference to nValue here
} // nValue goes out of scope here
通过引用返回有用的唯一时间是返回对类中现有数据成员的引用,或者返回对方法参数内的元素的引用。但在这两种情况下都没有必要归还任何东西;因为返回的引用已经可以自由地用于方法的调用者。
所以,我的结论是,根本不需要使用引用返回。我是对的吗?
答案 0 :(得分:11)
std::vector<>::operator[]
之类的操作返回对通过解除引用指针(并向其添加偏移量)获得的元素的引用。在这种情况下,指针是private
内部的vector
成员,因此用户不会在不破坏类的抽象的情况下获得自己的东西。
答案 1 :(得分:5)
这对于返回对堆栈上分配的引用的引用是不正确的。这根本行不通。
但是,通过引用返回仍然非常有用 - 例如,集合的索引操作符可以通过引用返回值,从而使您可以分配给集合中的该元素。
答案 2 :(得分:5)
通过引用返回有用的唯一时间是返回对类中现有数据成员的引用,或者返回对方法参数内元素的引用。
松散地说,是的。变量可能不是由类“拥有”(与其生命周期相关):它可以通过某些早期函数调用指定给类,或者类已知但不属于它的全局/单例,或者甚至在共享内存或堆中新分配的区域(虽然返回引用而不是指针表明所有权没有给予调用者),但最终该类必须具有对该数据的一些访问权。
但在这两种情况下都没有必要归还任何东西;因为返回的引用已经可以自由地用于方法的调用者。
不,因为对象可以拥有私有成员和受保护成员,并且可以向其他类或函数授予友谊,因此被调用函数完全有可能访问(并因此返回引用)调用者无法直接访问的某些数据到。
此外,许多函数找到一个特定的变量来做一些工作,然后返回对它的引用。如果调用者需要单独调用再次查找该变量,则可能效率低下(以及调用代码中的详细信息)。
所以,我的结论是,根本不需要使用引用返回。我是对的吗?
没有...由于上面的缺陷前提。
通过引用返回的另一个非必要但方便的用途是典型的流功能:
std::ostream& operator<<(std::ostream& os, const X& x)
{
return os << x.str();
}
上面,意思是指......
std::cout << x << y;
...被评估为......
(std::cout << x) << y;
operator<<(operator<<(std::cout, x), y)
所有人都很好地联系在一起。类似地:
while (std::cin >> x >> y)
...
...的工作原理不仅仅是因为对x和y的连续输入的链接,还因为std :: cin仍然可用于布尔上下文中的评估,最终调用另一个成员函数有效地询问是否流式传输运作有效。
答案 3 :(得分:1)
我只是想提一下,除了返回对私有/受保护数据成员的引用以及运算符的链接之外,模板元编程中还有一些技术可以使用通过引用返回临时变量的函数。这可以带来性能提升,但显然需要谨慎处理。 Boost.Proto库是表达式模板技术的一个示例,它使用对临时值的引用来避免创建临时值。对不起,我真的不能给出一个简单的例子......我不确定自己是否理解它,但我只是想指出即使是C ++中最不合逻辑的东西仍然被允许,如果允许的话,有人会找到一种方法来明智地使用它。这包括返回对临时的引用。
答案 4 :(得分:0)
试试这个。
int & DV(int & nX)
{
return nX *= 2;
}
// . . .
int i = 2;
int & j = DV(DV(i));
答案 5 :(得分:0)
我希望其他专家能够提出更详细的解释。我只想说一些C / C ++程序员使用引用类型的情况。
C ++引用类型只是对C的旧指针类型的语法增强。在C / C ++中,所有参数和返回值都是值类型。也就是说,将值复制到caller / callee或从caller / callee复制。显然,这不是所希望的操作。因此,当C / C ++程序员想要防止不必要的复制时,他们会使用指针或引用。
嗯..还有其他吗?
答案 6 :(得分:0)
通过引用返回的通常目的是,可以进行链式分配,如下所示:
MyVar1 = MyVar2 = Myvar3 = MyVar4;