我正在编写一个可以预处理数据并将其写入文件的应用程序。然后可以再次加载数据以在将来的运行中保存重新计算,但需要在进一步处理之前将其修改为通用格式。
如果没有预处理数据,该程序如下:
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
永远不再使用。一旦c
被调用,magic
将会发生什么,即编译器是否足够聪明c
?
答案 0 :(得分:3)
所有自动局部变量在超出范围时都会被销毁。调用c
后,magic
将在函数返回时自动销毁。
答案 1 :(得分:3)
当退出声明的范围时,对象将被立即销毁,而不是片刻之前。
编译器无法在“不再使用”的位置销毁本地,因为它们可能代表一个锁定句柄,需要保持活动状态并且活动直到块结束:
{
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()
。这将导致构造一个临时向量作为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()
的调用将成为该表达式的一部分。)