从方法返回后,局部结构变量不会被销毁

Local struct variable doesnt get destroyed after return from method

本文关键字:变量 结构 返回 方法 局部      更新时间:2023-10-16

我有以下代码

#include <iostream>
struct mystruct
{
    float x;
};
void fun(mystruct* ptr)
{
    mystruct str = {10};
    ptr = &str;
    std::cout<<"bbq";
}
class cls
{
public:
   mystruct* ptr;
   void fun()
   {
        mystruct str = {10};
        ptr = &str;
        std::cout<<"bbq";
   }
};
int main()
{
    mystruct* ptr = new mystruct;
    fun(ptr);
    std::cout<<"bbq";
    cls obj;
    obj.fun();
    std::cout<<"bbq";
}

首先在函数fun中设置指针ptr来指定局部结构的地址。当函数返回时,局部结构按预期被销毁。

但是在类中有一个方法对成员指针做同样的事情,但是在方法返回并且返回到主成员指针之后,成员指针仍然是设置的。方法返回后,方法局部变量不销毁吗?

您的第一个示例不是设置传递的指针,它是设置指针的本地副本,因为它是通过值传递的。为了使用实际的参数,您需要通过引用传递:

void fun(mystruct*& ptr);

局部变量在函数返回后被销毁。但是,即使在看到指针内部的值被设置为局部变量之后,也不能假设该局部变量没有被销毁。如果在将指针赋值给过期的对象后,任何时候对其解引用,则程序将出现未定义行为。

相关:局部变量的内存可以在其作用域之外访问吗?

代码很奇怪。例如在这个函数中:

void fun(mystruct* ptr)
{
    mystruct str = {10}; // create a structure
    ptr = &str;  // make ptr point to it
    std::cout<<"bbq";
}

ptr被设置为某个值,但是它从未被使用过。ptr是按值传递的,所以它不可能在这个函数之外产生影响。

:

class cls
{
public:
   mystruct* ptr;
   void fun()
   {
        mystruct str = {10}; // create local variable
        ptr = &str;  // make ptr point to it
        std::cout<<"bbq";
   }
};

您将类成员ptr设置为指向局部变量,但是当函数返回时该变量将被销毁,因此ptr将指向垃圾。ptr在你的例子中没有被再次使用,所以没有造成伤害,但它仍然很奇怪。

And in your main:

int main()
{
    mystruct* ptr = new mystruct; // make ptr point do a dynamically allocated object.
    fun(ptr); // call fun with a copy of the pointer
    std::cout<<"bbq";
    cls obj;
    obj.fun();
    std::cout<<"bbq";
    // That object that ptr is pointing to is never deleted.
}

在这种情况下,不删除分配的内容没有特别的危害,因为这是您的程序的结束,但是动态删除您的

我们可以通过这样做来诱导失败:

struct mystruct
{
    float x;
    ~mystruct() { x = 99; }
};

class cls
{
public:
   mystruct* ptr;
   void fun()
   {
        mystruct str = {10};
        ptr = &str;
        std::cout<<"bbq";
   }
   void fun2()
   {
       std::cout << ptr->x << std::endl;
   }
};
... 
  obj.fun();
  obj.fun2();

现在,可能会发生obj.fun2();打印99,或者它可能显示一些随机的其他数字,或者它可能崩溃。这是因为"使用已被销毁的对象是未定义的行为"——未定义的行为意味着c++标准没有定义会发生什么,并且"任何事情都可能发生",包括崩溃或挂起,或者它"按您的期望"工作。但是物体会被破坏。由于原始代码实际上并没有在它指向的对象被销毁后使用ptr,所以没有发生什么不好的事情(事实上,它甚至不是示例代码中未定义的行为-它只是未定义"在对象被销毁后使用指向的对象")。

编辑:

这个代码,然而:

mystruct* ptr = new mystruct;
fun(ptr);
std::cout<<"bbq";

导致内存泄漏,因为ptr永远不会被删除(如果fun在函数本身之外实际修改ptr,例如通过使用mystruct *&ptr作为参数,那么您将有一个不再引用的mystruct的内存块,这是一个更糟糕的内存泄漏-当然ptr中的值指向销毁的对象,所以您无论如何都不能使用ptr)