【发布时间】:2011-09-16 16:37:00
【问题描述】:
在C++中,如果我们在函数内部声明一个栈变量,是在函数结束时自动删除还是在程序执行结束时删除?
另外,对于 C 语言,这个问题的答案是否相同?
【问题讨论】:
在C++中,如果我们在函数内部声明一个栈变量,是在函数结束时自动删除还是在程序执行结束时删除?
另外,对于 C 语言,这个问题的答案是否相同?
【问题讨论】:
它在超出范围时被销毁。 C 也一样。
【讨论】:
自动变量在其封闭范围结束时自动销毁。
【讨论】:
为避免new 运算符的歧义,在离开函数时说变量“弹出”可能更合适:参见stack-based memory allocation。C 也是如此。
【讨论】:
对于堆栈声明的变量,调用析构函数并在超出范围时回收内存。
请注意,如果变量是在内部块(如 if 语句或循环)中声明的,这并不意味着在函数的末尾。
int main(int argc, char **argv)
{
int a = 3;
if (argc > 1)
{
int b = 5;
++b;
} // b is destructed here
// a is destructed here
// argv and argc are destructed here (or with a)
}
编辑:有人提出了一个很好的观点,即如何退出范围并不重要。所以...
#include <vector>
# include <exception>
int main(int argc, char **argv)
{
std::vector<int> myVector(10);
try
{
if (argc)
{
int a = 10;
int b = 12;
for (int c = 0; c < b; c++) // lol
{
int c_squared = c*c;
int theEleventhElement = myVector.at(c);
// the above will throw std::out_of_range at some point!
}
}
}
catch (std::out_of_range &ex)
{
// do nothing
}
}
当上述抛出时,堆栈将作为异常处理的一部分展开。因此,变量将按以下顺序销毁:
c_squaredcb 和 a(我认为是按照这个顺序,但我不知道标准中是否规定了)此时,终于有了一个只有myVector 仍在作用域内的catch 处理程序。该块忽略异常,然后main 结束——在该点myVector 被破坏。
【讨论】:
堆栈变量或多或少是通过减少堆栈指针从堆栈中删除的几个字节,它在函数结束时被删除,但是,不仅仅是再次向上移动堆栈指针(用户-定义类型)在 C++ 中,因为额外的破坏的东西。
在 C 中,这是一个简单的例子,向上移动堆栈指针以摆脱持有的变量。
【讨论】:
根据 3.7.2 对象的自动存储持续时间持续到创建它们的块退出,6.6 中有更多详细信息。 2:
在退出作用域时(无论如何完成),为所有构造的对象调用析构函数(12.4) 在该范围内声明的自动存储持续时间 (3.7.2)(命名对象或临时对象),在 他们的声明顺序相反。转出循环、转出块或返回已初始化的变量 具有自动存储持续时间的涉及销毁具有自动存储持续时间的变量 在转移点的范围内,但不在转移点的范围内。
【讨论】: