Gob*_*0st 26 c++ compiler-construction standards
C++标准规定返回对局部变量(在堆栈上)的引用是未定义的行为,那么为什么许多(如果不是全部)当前编译器只会发出警告呢?
struct A{
};
A& foo()
{
A a;
return a; //gcc and VS2008 both give this a warning, but not a compiler error
}
Run Code Online (Sandbox Code Playgroud)
如果编译器为此代码提供错误而不是警告,那会不会更好?
允许这个代码只用警告编译有什么好处吗?
请注意,这不是一个const
可以延长临时使用寿命的参考资料.
Dav*_*eas 23
从编译器的角度来看,验证是否返回对临时的引用几乎是不可能的.如果标准规定要将其诊断为错误,那么编写编译器几乎是不可能的.考虑:
bool not_so_random() { return true; }
int& foo( int x ) {
static int s = 10;
int *p = &s;
if ( !not_so_random() ) {
p = &x;
}
return *p;
}
Run Code Online (Sandbox Code Playgroud)
上述程序运行正确且安全,在我们当前的实现中,保证foo
将返回对static
变量的引用,这是安全的.但是从编译器的角度来看(并且使用单独的编译,not_so_random()
无法访问实现,编译器无法知道程序是否格式正确.
这是一个玩具示例,但您可以想象具有不同返回路径的类似代码,其中p
可能引用返回的所有路径中的不同长寿命对象*p
.
Ker*_* SB 10
未定义的行为不是编译错误,它不是一个格式良好的C++程序.并非每个不正常的程序都是不可编辑的,这是不可预测的.我敢打赌,原则上计算机无法确定给定的程序文本是否是格式良好的C++程序.
您始终可以添加-Werror
到gcc以使警告终止编译并显示错误!
添加另一个最喜欢的SO主题:您是否也想++i++
引起编译错误?
如果返回指向本地内部函数的指针/引用,只要不取消引用从函数返回的指针/引用,就可以很好地定义行为.
仅当退出指针时,它才是未定义的行为.
它是否是未定义的行为取决于调用函数的代码而不是函数本身.
因此,在编译函数时,编译器无法确定行为是未定义还是定义良好.它能做的最好的事情是警告你一个潜在的问题,它确实存在!
代码示例:
#include <iostream>
struct A
{
int m_i;
A():m_i(10)
{
}
};
A& foo()
{
A a;
a.m_i = 20;
return a;
}
int main()
{
foo(); //This is not an Undefined Behavior, return value was never used.
A ref = foo(); //Still not an Undefined Behavior, return value not yet used.
std::cout<<ref.m_i; //Undefined Behavior, returned value is used.
return 0;
}
Run Code Online (Sandbox Code Playgroud)
参考C++标准:
第3.8节
在对象的生命周期开始之前但是在对象将占用的存储之后已经分配了34),或者在对象的生命周期结束之后并且在对象占用的存储被重用或释放之前,任何指针指的是可以使用对象将被定位或存在的存储位置,但仅限于有限的方式. 这样的指针指的是已分配的存储(3.7.3.2),并且使用指针就像指针一样type void*
,是明确定义的.这样的指针可以被解除引用,但是所得到的左值可以仅以有限的方式使用,如下所述.如果对象将是或具有非平凡析构函数的类类型,并且指针用作delete-expression的操作数,则程序具有未定义的行为.如果对象将是或者是非POD类类型,则在以下情况下,程序具有未定义的行为:
- .......
归档时间: |
|
查看次数: |
1074 次 |
最近记录: |