Dre*_*kes 36 c++ return-by-reference
以下代码调用未定义的行为.
int& foo()
{
int bar = 1234;
return bar;
}
Run Code Online (Sandbox Code Playgroud)
g ++发出警告:
警告:返回对局部变量'bar'的引用[-Wreturn-local-addr]
clang ++也是:
警告:返回与本地变量'bar'关联的堆栈内存[-Wreturn-stack-address]
为什么这不是编译错误(忽略-Werror)?
是否存在将ref返回到本地var的情况?
编辑正如所指出的,规范要求这是可编译的.那么,为什么规范不禁止这样的代码呢?
Rei*_*ica 38
我要说的是,要求这使得程序格式错误(也就是说,使其成为编译错误)会使标准复杂化,效果甚微.在确定此类案例时,您必须准确地说明标准,并且所有编制者都必须实施它们.
如果指定的太少,则不会太有用.并且编译器可能已经检查了这个以发出警告,并且真正的程序员-Wall_you_can_give_me -Werror无论如何都要进行编译.
如果指定太多,编译器很难(或不可能)实现该标准.
考虑这个类(您只有标题和库):
class Foo
{
int x;
public:
int& getInteger();
};
Run Code Online (Sandbox Code Playgroud)
这段代码:
int& bar()
{
Foo f;
return f.getInteger();
}
Run Code Online (Sandbox Code Playgroud)
现在,是否应该制定标准以使其形成不良?可能不会,如果Foo实现如下:
#include "Foo.h"
int global;
int& Foo::getInteger()
{
return global;
}
Run Code Online (Sandbox Code Playgroud)
同时,它可以像这样实现:
#include "Foo.h"
int& Foo::getInteger()
{
return x;
}
Run Code Online (Sandbox Code Playgroud)
这当然会给你一个悬垂的参考.
我的观点是,编译器无法确切地知道返回引用是否正常,除了一些简单的情况(返回对函数范围自动变量或非引用类型的参数的引用).我认为将标准复杂化并不值得.特别是因为大多数编译器已经将此作为实施质量问题提出警告.
出于同样的原因,C允许您返回指向已释放的内存块的指针.
它根据语言规范有效.这是一个可怕的坏主意(和无处接近到被保证工作),但它仍然是因为它不禁止有效.
如果你问为什么标准允许这个,那可能是因为,当引用引用时,这就是它们的工作方式.标准的每次迭代都有一定的指导方针(例如最大限度地减少"破坏变更"的可能性,那些使现有格式良好的程序无效的标准),标准是用户和实施者之间的协议,毫无疑问比实施者更多的实施者在委员会:-)
可能值得推动这个想法作为一个潜在的变化,并看到ISO说什么,但我怀疑它将被视为那些"突破性变化"之一,因此非常怀疑.
此外,因为您可能想要获取当前堆栈指针(无论您的特定实现是什么意思).
这个功能:
void* get_stack_pointer (void) { int x; return &x; };
Run Code Online (Sandbox Code Playgroud)
AFAIK,如果不取消引用结果指针,则不是未定义的行为.
比这个更便携:
void* get_stack_pointer (void) {
register void* sp asm ("%esp"); return sp; }
Run Code Online (Sandbox Code Playgroud)
至于为什么你可能想要获得堆栈指针:好吧,有些情况下你有正当理由得到它:例如保守的Boehm垃圾收集器需要扫描堆栈(所以想要堆栈指针和堆栈底部) .
如果你返回一个C++引用,你只能使用&一元运算符获取它的地址,那么获得这样一个地址是IIUC合法的(恕我直言,你可以做的唯一合法操作).
获取堆栈指针的另一个原因是获取NULL任何堆,本地或静态数据的非指针地址(您可以例如散列).但是,您可以使用(void*)1或(void*)-1用于此目的.
所以编译器只是警告这个.
我想C++编译器应该接受
int& get_sp_ref(void) { int x; return x; }
void show_sp(void) {
std::cout << (&(get_sp_ref())) << std::endl; }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6784 次 |
| 最近记录: |