由于返回对局部变量的引用,我被一个令人讨厌的未定义行为所困扰。
我们知道它是邪恶的,通常编译器打印一个很好的warning
来告诉我们......好吧gcc(3.4.2)似乎并没有把检查推得太远。
std::string get_env_value(std::string const& key);
std::string const& get_phase()
{
std::string const& phase = get_env_value("PHASE"); // [1]
std::cout << "get_phase - " << phase << '\n';
return phase; // [2]
}
这没有任何故障编译,但我们陷入了未定义行为的讨厌境界。
行[1]
没问题,因为标准指定应该扩展绑定到const引用的变量的生命周期以匹配const引用的生命周期。
行[2]
似乎也没问题......
在我看来,静态分析应该能够告诉我[1]
使用“终身延期”,[2]
并不安全,但我猜想它会变得很丑陋......
答案 0 :(得分:5)
该标准未涵盖[2]
。它允许rvalue绑定到const引用,但是这不允许你返回一个const引用,并且它具有被绑定的rvalue的生命周期。
真实的,静态分析可以抓住这个,但一如既往地权衡。 C ++编译本身就足够慢,因此编译器编写者必须权衡进一步静态分析的好处,这可能使他们能够根据增加的编译时间产生更好的诊断。
答案 1 :(得分:2)
不,我不认为标准提及/涵盖了这个具体案例。
VS 2010提供编译警告(/ Za,/ W4)。
所以,它看起来确实是一种可以诊断的疾病。
所以,我稍微调整了这个函数,只是为了创建多个返回路径:
std::string const& get_phase()
{
std::string const& phase = get_env_value("PHASE"); // [1]
std::cout << "get_phase - " << phase << '\n';
if(1){
while(1){
return phase;
}
}
return phase; // [2]
}
现在,VS不会像之前那样报告警告。
作为一个例子,乍一看,它看起来编译器应该很容易检测并捕获并非所有路径都返回一个值。但是编译器(例如VS)没有。
int get_phase()
{
char ch;
if(ch){
return 0;
}
// nothing returned from here.
}
所以,我猜OP中的代码可能与上面显示的例子一样具有诊断条件的复杂性,但我不确定。唯一的好处是标准在这种情况下是明确的。
$ 6.6.3 / 2 - “流了下来 函数的结尾相当于a 没有价值的回报;这导致了 一个未定义的行为 价值回归功能。“
回到OP中的代码,我想标准并没有强制要求这个条件成为可诊断的条件,因此编译器可以随心所欲地做。基本上可以理解,返回的参考指向已经被破坏的对象。因此,访问此类对象将导致未定义的行为