我正在编写一个可以预处理数据并将其写入文件的应用程序。然后可以再次加载数据以节省 future 运行时的重新计算,但需要在进一步处理之前将其修改为通用格式。
没有预处理数据,程序看起来像:
void no_preprocess(std::vector<T>& a)
{
std::vector<P> b = hard_work(a);
magic(a, b);
}
以及预处理后的数据:
void foo(std::vector<T>& a, std::string path)
{
std::vector<D> c = read(path);
std::vector<P> b = easy_work(a, c);
// Is c now free?
magic(a, b);
}
一旦 easy_work
完成,c
就不再使用了。一旦 magic
被调用,c
会发生什么,即编译器是否足够聪明免费 c
?
最佳答案
当退出声明它的范围时,对象将立即被销毁,而不是之前的片刻。
编译器无法在局部变量“不再使用”时销毁局部变量,因为它们可能代表,例如,需要保持事件状态的锁句柄,直到 block 结束:
{
std::lock_guard<std::mutex> guard(a_mutex);
do_something_on_shared_structure();
// guard is destructed here.
}
guard
在其构造完成后“不再使用”,但编译器必须发出代码,等待调用以下函数来销毁对象,否则锁将被提前发布。
编译器根本不允许提前析构对象,因为析构函数可能有副作用(在这种情况下释放锁)。
因此您的情况的答案是相同的:c
将在函数返回之前立即销毁,即 在 magic()< 的调用之后
,因为编译器不知道调用 c
的析构函数时会发生什么副作用。
如果想提前析构c
,可以将read()
的结果直接传给easy_work()
。这将导致构造一个临时 vector 作为 easy_work()
的第二个参数,它会在 easy_work()
返回后立即被销毁:
void foo(std::vector<T>& a, std::string path)
{
std::vector<P> b = easy_work(a, read(path));
magic(a, b);
}
(请注意,您不能将其简化为 magic(a, easy_work(a, read(path)))
因为 read()
返回的临时文件将继续在调用 magic()
时存在。C++ 标准规定,临时对象的存在时间与它们出现的完整表达式 一样长,不再存在,并且调用在这种情况下,magic()
将成为该表达式的一部分。)
关于c++ - 内部函数调用后未使用的局部变量是否被释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26658653/