请考虑以下代码:
class Test() {
public:
Test()
{
memset( buffer, 0, sizeof( buffer ) );
}
void Process()
{
printf( buffer );
}
private:
char buffer[1000];
};
int main()
{
Test().Process();
char buffer[1000] = {};
print( buffer );
return 0;
}
我无法推断出main中的buffer
是否允许重用先前由class Test
临时对象占用的内存。根据标准自动存储(3.7.2 / 1)must persist for at least until the block ends。
我找不到强制临时对象使用自动存储的措辞,除了6.6 / 2,其中描述了一个跳转语句,并且说明退出范围[...],析构函数(12.4)调用具有自动存储持续时间(3.7.2)(命名对象或临时值)的所有构造对象,这似乎意味着临时使用自动存储。
是否需要临时使用自动存储?上面代码中的main
中的局部变量是否允许重用以前由临时占用的内存,还是应该使用不同的存储?
答案 0 :(得分:6)
临时的生命周期(除非绑定到const&
)延伸到完整表达式的末尾。在你的情况下,main
中的第一行。允许编译器重用相同的内存,但它是否具有实现细节(即实现质量)
12.2 [class.temporary]
/ 3 [...]临时对象作为评估的最后一步被销毁 完整表达式(1.9)(词法上)包含创建它们的点。[...]
/ 4有两种情况下,临时表在与完整表达式结束时不同的点被销毁。第一个上下文是表达式作为定义对象的声明符的初始值设定项。 [...]
/ 5第二个上下文是指引用绑定到临时引用。
由于您既不是例外,Test
临时属于第一类,已销毁作为评估第一行的最后一步。
答案 1 :(得分:3)
3.7.2 / 1专门讨论了块范围变量。那些存储必须持续存储。但是,正如您所发现的,临时工具做具有自动存储持续时间,但不是块范围变量。 (见3.3.3,块范围与名称相关)。
答案 2 :(得分:2)
语法Test()
创建一个临时语句。这与名为
Test iHaveAName;
命名对象具有块持续时间;它将一直存在直到阻止结束。临时表达持续时间;当表达式结束时它将被销毁。
因此,如果您执行Test().Process()
,则Test()
临时用户将活得足够长,Process()
可以完成。
答案 3 :(得分:1)
Test
实例一直存在;
那里。是否未指定buffer
是否重用用于Test
实例的存储。 AFAIK,标准中没有任何内容阻止编译器重用该空间。
答案 4 :(得分:0)
它是实现定义的。智能编译器可以通过对齐堆栈指针来优化代码,以便buffer
可以重用内存。