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

C++ 内部函数调用后是否释放未使用的局部变量?,c++,memory-management,C++,Memory Management,我正在编写一个应用程序,其中数据可以预处理并写入文件。然后可以再次加载数据,以保存将来运行时的重新计算,但需要在进一步处理之前修改为通用格式 如果没有预处理的数据,程序看起来像: void no_preprocess(std::vector<T>& a) { std::vector<P> b = hard_work(a); magic(a, b); } void no_预处理(std::vector&a) { std::vectorb=辛勤工作(

我正在编写一个应用程序,其中数据可以预处理并写入文件。然后可以再次加载数据,以保存将来运行时的重新计算,但需要在进一步处理之前修改为通用格式

如果没有预处理的数据,程序看起来像:

void no_preprocess(std::vector<T>& a)
{
    std::vector<P> b = hard_work(a);
    magic(a, b);
}
void no_预处理(std::vector&a)
{
std::vector

b=辛勤工作(a); 魔术(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);
}
void foo(std::vector&a,std::string path) { std::vector c=读取(路径); std::vector

b=容易的工作(a,c); //c现在免费吗? 魔术(a,b); }


一旦
easy\u工作
完成,
c
将不再使用。调用
magic
后,
c
会发生什么情况,也就是说,编译器是否足够聪明,可以自由使用
c

所有自动局部变量在超出范围时都会被销毁<调用
magic
后,当函数返回时,code>c将自动销毁所有自动局部变量,当它们超出范围时<调用
magic
后,当函数返回时,code>c将自动销毁。当对象退出声明它的作用域时,它将立即销毁,而不是一刻之前

编译器无法在局部变量变为“不再使用”时销毁它们,因为它们可能表示一个锁句柄,需要在块结束前保持活动状态:

{
    std::lock_guard<std::mutex> guard(a_mutex);
    do_something_on_shared_structure();

    // guard is destructed here.
}

(请注意,您不能将其简化为
magic(a,easy_work(a,read(path)))
,因为
read()
返回的临时值将在
magic()期间继续存在“C++”标准称,“临时”存在于其出现的全部表达式中,并且不再存在,并且调用<代码> MAGICE()/CUT>将是该表达式中的一部分。)

< P>在退出声明的范围时,对象将立即被破坏,而不是在一分钟之前。 编译器无法在局部变量变为“不再使用”时销毁它们,因为它们可能表示一个锁句柄,需要在块结束前保持活动状态:

{
    std::lock_guard<std::mutex> guard(a_mutex);
    do_something_on_shared_structure();

    // guard is destructed here.
}

(请注意,您不能将其简化为
magic(a,easy_work(a,read(path)))
,因为
read()
返回的临时值将在
magic()期间继续存在“C++”标准称,“临时”的存在只要它们出现的全部表达式,并且不再存在,并且调用<代码> MAGICE()/CUT>将是该表达式的一部分。它在声明之后不被使用。是的,因为所有C++实现都有一个。顺便说一句,你应该使用@cdhowie哦,亲爱的,我已经纠正了这个问题@你指的是使用
std::move
?不是,而是指C++11的许多新特性;值得注意的是,
auto
和λ(以及函数式编程风格)。
c
甚至不被
easy\u work()
使用。它在声明之后不被使用。是的,因为所有C++实现都有一个。顺便说一句,你应该使用@cdhowie哦,亲爱的,我已经纠正了这个问题@你指的是使用
std::move
?不是,而是指C++11的许多新特性;特别是
auto
和λ(以及函数式编程风格)。回答得很好。尽管我仍然有点惊讶,编译器不允许以这种方式进行优化。在您的锁示例中,是否不清楚
a_mutex
是一个全局变量(或者至少不是一个未在范围内声明的变量),因此不能安全地删除,而在我的示例中
c
是在范围内声明的,可以安全地删除?@Daniel
a_mutex
没有被破坏,而是
guard
,也就是说,它是一个局部变量。编译器并不假装知道这些类型的作用。例如,在您的例子中,销毁
c
还意味着销毁向量中的每个
D
对象--如果这些析构函数有副作用,并且您希望销毁延迟到函数结束时,该怎么办?如果您在
magic()
中使用对
D
对象的引用,并且编译器很早就破坏了这些对象,该怎么办?@Daniel下面是我的意思示例:--在这种情况下,如果编译器提前解构了
c
,它将解构通过
b
中的
P
对象保存引用的所有
D
对象。编译器不够聪明,无法解决所有这些问题,如果在不同的翻译单元中定义了
easy\u work()
,那么编译器甚至无法解决这些问题,因为它看不到函数体。避免此问题的最简单方法是禁止此类优化。它太容易失败了,回答得很好。尽管我仍然有点惊讶,编译器不允许以这种方式进行优化。在您的锁示例中,是否不清楚
a_mutex
是一个全局变量(或者至少不是一个未在范围内声明的变量),因此不能安全地删除,而在我的示例中
c
是在范围内声明的,可以安全地删除?@Daniel
a_mutex
没有被破坏,而是
guard
,也就是说,它是一个局部变量。编译器并不假装知道这些类型的作用。例如,在您的例子中,销毁
c
还意味着销毁向量中的每个
D
对象--如果这些析构函数有副作用,并且您希望销毁延迟到函数结束时,该怎么办?如果您在
magic()
中使用对
D
对象的引用,并且编译器很早就破坏了这些对象,那么会怎么样?@Daniel下面是我的意思示例:--在这种情况下,如果编译器