代码之家  ›  专栏  ›  技术社区  ›  tTt

使用堆栈中的值重新分配指针

  •  1
  • tTt  · 技术社区  · 5 月前

    这是未定义的行为吗

    #include <iostream>
    #include <string>
    using namespace std;
    
    class A {
    public: 
        ~A() { cout << "~A\n"; }
    };
    
    void f(A*& d) 
    {
        A e;
        *d = e;
    }
    
    int main()
    {   
        A *u = new A;
        f(u);
        delete u;
     
        return 0;
    } 
    

    由于f函数中的e是局部变量,u指针何时会被删除?

    2 回复  |  直到 5 月前
        1
  •  4
  •   Ted Lyngmo    5 月前

    这是未定义的行为吗

    不,不是。

    什么时候 u 指针将被删除,因为 e f 函数是局部变量吗?

    e 是一个局部变量,当它超出作用域时(即函数返回时)将被销毁。

    任务 *d = e; 仅指定值 e 以实例 A 那个 d 点在。 u 当您这样做时,将被删除 delete u; 在里面 main 。没问题。

    一个警告标志是,您可以通过引用获取原始拥有指针。这意味着函数实际上可以分配 d 指向不同的 A. ( d = new A; 然后原始指针将丢失并且将泄漏内存。 d = &e; 情况会更糟,因为你们俩都会漏水,而且什么时候会漏水 f 返回, u 将是一个悬挂的指针 删除u; 会有 未定义行为 .

        2
  •  1
  •   463035818_is_not_an_ai    5 月前

    您不会更改指针指向的位置。 A *u = new A; 使 u 指向动态分配 A 对象。 *d = e; 指定值 e 对于这个对象。最终 delete u; 删除动态分配的对象。它总是同一个对象(第二个对象在函数本地具有自动存储功能 f ).

    如果你考虑到可以在不改变代码功能的情况下更改函数签名,这可能会变得更加清楚:

    void f(A* d) 
    {
        A e;
        *d = e;
    }
    

    当指针按值传递时,函数不可能更改传递给它的指针的值。

    看看它是如何编译的: https://godbolt.org/z/63M9ozf3M


    也许你脑海中的代码存储了一个指向对象的指针,并具有自动存储持续时间, d = &e; 。然后尝试通过中的悬挂指针删除已删除的对象 main 确实会引发未定义的行为。