c++ - 内部函数调用后未使用的局部变量是否被释放?

标签 c++ memory-management

我正在编写一个可以预处理数据并将其写入文件的应用程序。然后可以再次加载数据以节省 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/

相关文章:

c++ - C++中堆的损坏

c++ - 如何检查双指针中的空白空间(NULL)

c - 如何在 C 中创建保存静态数组的动态数组?

java - 客户端-服务器网络入门

c++ - 在 C++ 中流式传输字符串文字

c++ - 为什么 BOOST_TEST((Iterator == Iterator)) 需要额外的括号?

c++ - 为什么无法在 C++ 中撤消 'using'?

c++ - 强制 Boost 使用 C++11 线程

c - c 中自定义存储分配器的示例或文档?

algorithm - 优先分配算法如何减少内存碎片?