从this thread可以清楚地看到,字符串文字不能用于返回const字符串&的函数。因为存在从const char *到std :: string的隐式转换,它创建了一个临时的。
但是,如果我的返回类型完全匹配并且不需要转换,为什么我会收到警告“警告:返回对临时的引用”,例如:
include <iostream>
const int& test(){
return 2;
}
int main(){
std::cout << test();
}
在返回值2上不需要进行隐式转换,为什么会出现警告?我认为使用test()与执行
几乎相同 const int& example = 2;
完全有效。此外,如果我将2更改为2.2(因此它是一个双倍)程序仍然运行(具有相同的警告),尽管事实上有从double到int的转换?我不应该遇到类似于const char *如何返回到字符串引用的问题,如果有从double到int的转换吗?
答案 0 :(得分:1)
仍然创建临时。 §8.5.3/(5.2.2.2)适用 1 :
否则,会创建一个临时类型“ cv1
T1
” 初始化表达式中的copy-initialized(8.5)。参考资料 然后绑定到临时。
这也适用于你的第二个例子。它不适用于类类型的prvalues或标量xvalues:两者
const A& a = A();
// and
const int& i = std::move(myint);
不要介绍一个临时的。但是,这并没有改变最终结果:在任何情况下,绑定到引用的临时将在return
语句结束时销毁 - 第12.2节/(5.2):
函数
return
语句(6.6.3)中返回值临时绑定的生命周期未扩展;暂时的 在return
中的完整表达结束时被销毁 言。
也就是说,临时在函数退出之前被销毁,因此你的程序会导致未定义的行为。
1 我可以继续引用整个列表来说明它的原因,但这可能会浪费答案空间。
答案 1 :(得分:0)
从const char *到std :: string的隐式转换,它创建了一个临时的
您正在混淆这两个主题。隐式转换并不是唯一可以创造临时转换的东西:
const std::string& test() {
return std::string("no implicit conversions here.");
}
没有隐式转换来创建string
,但创建的string
仍然是临时的,因此您仍然会返回对临时对象的引用。
在您的示例中,2
仍然是临时值,临时存储在堆栈的某个位置,并返回其位置/地址,以便调用者可以获取该值,但不应该这样。