2015-05-31 31 views
3

this thread很明显,字符串文字不能用于返回常量字符串&的函数,因为存在从const char *到std :: string的隐式转换,从而创建临时。返回引用临时(内置类型)

既然这样,为什么我得到一个警告“警告:返回引用到一个临时”如果我的返回类型完全匹配,也没有必要转换,如:

include <iostream> 

const int& test(){ 
    return 2; 
} 

int main(){ 

    std::cout << test(); 

} 

发生不需要的隐式转换关于2的返回值,为什么会有警告?我认为使用测试()将几乎是相同的做

const int& example = 2; 

这是完全有效的。此外,如果我将2更改为2.2(因此它是双精度型),程序仍然运行(具有相同的警告),尽管事实上存在从double到int的转换?如果有从double到int的转换,我不应该遇到类似于const char *返回到字符串引用的问题吗?

+4

引用不能直接绑定到右值。相反,构造一个类型为“int”的临时对象(在'test'内部)并初始化为2,并返回对该对象的引用。暂时在此刻被摧毁,导致参考悬而未决。 –

+0

@Igor Tandetnik我明白了,谢谢。对我而言,我链接的线程使得它看起来像是只有在发生隐式转换时才会遇到的问题。 – Silversonic

+0

和它“有效”的“事实”,好吧,那只是UB。 –

回答

1

临时创建仍然存在。 §8.5.3/(5.2.2.2)适用:

否则,临时型“CV1T1”创建并从初始化表达式 副本初始化(8.5)的。然后将参考 绑定到临时。

这也适用于你的第二个例子。它不适用于类类型,或标xvalues的prvalues:两个

const A& a = A(); 
// and 
const int& i = std::move(myint); 

不引入一个临时的。

的寿命: - :然而,这并不改变最终结果§12.2/(5.2)。在任何情况下,被结合到参考临时将在return语句的末尾被破坏函数return声明(6.6.3)中的返回值的临时绑定不被扩展;临时 在return 声明中的完整表达式的末尾被销毁。

也就是说,在函数甚至退出之前临时被销毁,因此你的程序会引发未定义的行为。


我可以继续下去,并引用整个列表,说明为什么这样做,但大概是答案空间的浪费。

0

从为const char *的隐式转换为std ::它会创建一个临时

你混为一谈两个主题字符串。隐式转换是不是可以创建临时对象的唯一的事情:

const std::string& test() { 
    return std::string("no implicit conversions here."); 
} 

没有隐式转换创建string,但创建string仍然是暂时的,所以你还是返回到临时对象的引用。

在你的例子中,2仍然是一个临时值,临时存储在堆栈的某个位置,并且其位置/地址返回,因此调用者可以获取该值,但不应该这样做。