首页 > 解决方案 > 析构函数何时此对象超出范围

问题描述

class Entity {
    //attributes
public:
    float X, Y;
    Entity() {
        X = 0;
        Y = 0;
        cout << "Created Entity!" << endl;
    }
    ~Entity() {
        cout << "Entity Destroyed!" << endl;
    }
    void Print() {
        cout << X << ", " << Y << endl;
}




};
void func() {
    Entity e;
    e.Print();
    
}
int main()
{
    func();
    cout << "b";
}

所以我有点难以理解这里到底发生了什么,我不明白 e 何时以及如何超出范围。func 创建 e 然后调用方法函数,但是只有当我在 main 中调用 func 时才执行所有这些,对吗?因此,只有当我在 main e 中调用 func 并调用该方法时,它究竟是如何超出范围的?

就像有人可以试着解释一下,就像我是一个 5 岁的孩子一样吗?仅当在 main 中调用 func 时才创建实体,对吗?e 什么时候可能超出范围?

标签: c++

解决方案


我不明白 e 何时以及如何超出范围

范围e从其声明到其封闭块范围结束的所有内容:

void func()
{                 // start of block scope
    Entity e;     // e created in the enclosing block scope here
    e.Print();    
}                 // end of block scope, e (and any other automatic locals) destroyed

但是只有当我在 main 中调用 func 时才会执行所有这些操作吗?

现在你混淆了两件事:

  1. 范围是源代码中e有效标识符的部分(并且指的是同一个对象,以防您在其他代码中有其他同名的变量)。这是静态的,在编译时都是已知的。
  2. 控制流是什么时候func实际执行的,进入其块作用域,执行函数体中的语句,最后退出块作用域(同时销毁任何自动本地对象)。这发生在运行时,并且是动态的(从某种意义上说,它可能取决于条件逻辑或输入)。

因此,只有当我在 main e 中调用 func 并调用该方法时,它究竟是如何超出范围的?

它具有自动作用域,因此它的作用域在封闭块出现时结束。对于e,那是func执行完成且控制返回到 之前的时间main

... e 什么时候可能超出范围?

在调用 to 之后尝试引用ein 。它编译吗?mainfunc

不,因为e不是此范围内的标识符。

有什么选择?每个大型程序都会累积在全局命名空间中使用过的每个变量名。它会很快变得难以管理,事实上这正是我们使用局部变量而不是全局变量的原因。


请注意,我们可以通过返回一些东西来将作用域生命周期分开。如果我们选择具有动态生命周期的东西:

std::unique_ptr<Entity> foo()
{                                           // block begins
  std::unique_ptr<Entity> e;                // e scope begins
  e.reset( new Entity );                    // *e lifetime begins
  e->Print();
  return std::move(e);                      // *e moves to return value
}                                           // e destroyed

int main()
{
  auto f = foo();                           // *e is now called *f
  f->Print();
}                                           // f destroyed and deletes *f
  1. 可以看到有一个匿名对象(new*e*f
  2. e具有与以前相同的(块)范围
  3. e具有相同的(自动)生命周期,因此在超出范围时会被销毁
  4. 原来已知的对象*e被移交给f并保持存在。它仍然没有可以绑定到范围的自己的标识符。
  5. f还具有块范围和自动生命周期
  6. *f(以前称为 的动态对象*e)被销毁f 只是因为我们没有将它移到其他地方。

推荐阅读