如何防止函数释放局部变量的内存?

时间:2019-07-03 23:11:08

标签: c++ pointers

我试图通过存储函数的地址来保存函数中的局部变量。但是,即使我将其地址存储到指针变量中之后,似乎编译器也会自动释放该变量的内存。

我处于一种情况(与下面的代码不完全相同),我必须让一个类的成员变量存储在函数中声明的变量的地址。

#include <stdio.h>

static int* p;

void foo(){
    int a = 5;
    p = &a;
}

int main(){
    foo();

    //some delay

    printf("*p = %d\n",*p);
}

理想情况下,*p应该为5,但最终得到的数字不是5,并且在我重新运行脚本的很多时候都不同。我认为a中分配给foo的内存会自动释放。我如何确定*p是5,尽管有任何延迟?

4 个答案:

答案 0 :(得分:4)

解决方案1-使用new和delete动态分配内存

如果您希望函数退出后可以访问存储位置,则应使用new动态分配它:

int* foo() {
    int* p = new int(5); // Get pointer to int with value of 5
    return p; 
}

由于该指针分配了new,它会一直存在直到您调用delete为止:

int main() {
    int* myPtr = foo(); 

    // Do stuff with myPtr

    delete myPtr; // Free it, now that it's no longer needed.
}

潜在问题

当人们谈论必须使用C ++进行手动内存管理时,这通常是他们的意思。弄清楚何时调用对象上的delete可能很棘手,而且很容易搞砸。

解决方案2-变量a即使在函数退出后仍然存在,并且每次调用该函数时变量a都是相同的

如果我们将a标记为静态,则每次调用该函数时,它将具有相同的内存地址,并且不会被释放:

int* p;
void foo() {
    static int a = 5;

    p = a;
}

int main() {
    foo(); 

    // stuff...

    std::cout << *p << '\n'; // Prints 5, unless you modified *p
}

但是为什么?

通常,当给出一个很好的答案时,了解为什么被问者想要做某事很有帮助。您没有提供有关为什么要这样做的任何信息,因此我不知道(具体地)提出什么建议。

答案 1 :(得分:1)

如果要在函数调用后保留foo中的变量,那么必须将a设为静态变量。 C ++是基于堆栈的计算机:这意味着变量的生存期仅限于其范围。在您的示例中,a仅限于foo的范围。如果将变量设为静态,则它将把变量的生存期延长到顶级范围,但会限制您对函数内的a的访问。

我觉得您要尝试执行的操作非常有代码臭味,但这是您要求的:

#include <stdio.h>

static int* p;

void foo(){
    static int a = 5; // a will only be initialized to 5 once (see magic statics)
    p = &a;
}

int main(){
    foo();

    //some delay

    printf("*p = %d\n", *p);
}

在此示例中,可以保证a会在首次调用时进行初始化,并且在程序结束前不会被重用或删除。

答案 2 :(得分:0)

是使用自动存储变量的意义,当它们超出范围时将消失。 在销毁它们后指向它们是不确定的行为。 UB可能会为您返回正确的值,错误的值或使您的应用程序崩溃或其他任何原因。

如果要保留它,请不要使其位于本地。使用(并返回)unique_ptr / shared_ptr(尽管我仍然看不到为什么要在代码中这样做)。

所有提示静态变量的答案都是错误的。尽管它会暂时起作用,但如果养成习惯,它肯定会带来很多其他问题。

答案 3 :(得分:-1)

使用静态变量,它将解决您的问题5。 另一方面,由于它是局部变量,因此不会保存该内存。