【问题标题】:C++ - What does "Stack automatic" mean?C++ - “堆栈自动”是什么意思?
【发布时间】:2010-09-07 00:05:13
【问题描述】:

我在网上浏览时遇到了this post,其中包括这个

"(写得很好)C++ 非常棒 使堆栈自动的长度 对象“就像”原语一样工作, 正如 Stroustrup 的建议所反映的那样 “像整数一样做”。这需要一个 更大程度地遵守 面向对象的原则 发展:你的课不对 直到它“像”一个 int 一样工作, 遵循“三法则” 保证它可以(就像一个int) 被创建、复制和正确地创建 作为堆栈自动销毁。”

我已经编写了一些 C 和 C++ 代码,但只是顺带一提,从来没有什么严肃的事情,但我只是好奇,这到底是什么意思?

谁能举个例子?

【问题讨论】:

    标签: c++ oop


    【解决方案1】:

    如果我错了,请纠正我,但我认为复制操作对于充分利用自动堆栈清理不是强制性的。 例如,考虑一个经典的 MutexGuard 对象,它不需要复制操作就可以作为堆栈自动使用,是吗?

    【讨论】:

    • 没错。您仍然应该将复制构造函数声明为私有(或在 C++0x 中,已删除),以防止有人自动调用它,这将导致双重释放拥有的资源。三条规则并不是说您必须定义一个复制构造函数,而是说您必须阻止编译器定义一个(通过提供您自己的或使其不可访问/删除)。
    【解决方案2】:

    除了其他答案:

    C++ 语言实际上有auto 关键字来显式声明对象的存储类。当然,这是完全没有必要的,因为这是隐含的局部变量存储类,不能在任何地方使用。 auto 的反义词是 static(本地和全局)。

    以下两个声明是等价的:

    int main() {
        int a;
        auto int b;
    }
    

    因为关键字完全没用,它实际上会在下一个 C++ 标准(“C++0x”)中被回收并获得新的含义,即它让编译器从其初始化中推断变量类型(如@ 987654325@ C#):

    auto a = std::max(1.0, 4.0); // `a` now has type double.
    

    【讨论】:

      【解决方案3】:

      堆栈对象由编译器自动处理。

      当范围离开时,它被删除。

      {
         obj a;
      } // a is destroyed here
      

      当您对“新”对象执行相同操作时,您会遇到内存泄漏:

      {
          obj* b = new obj;
      }
      

      b 没有被破坏,所以我们失去了回收 b 拥有的内存的能力。更糟糕的是,对象无法自行清理。

      在 C 中以下是常见的:

      {
         FILE* pF = fopen( ... );
         // ... do sth with pF
         fclose( pF );
      }
      

      在 C++ 中我们这样写:

      {
         std::fstream f( ... );
         // do sth with f
      } // here f gets auto magically destroyed and the destructor frees the file
      

      当我们忘记在 C 示例中调用 fclose 时,文件不会被关闭并且可能不会被其他程序使用。 (例如无法删除)。

      另一个例子,演示对象字符串,它可以被构造、分配给并在退出范围时被销毁。

      {
         string v( "bob" );
         string k;
      
         v = k
         // v now contains "bob"
      } // v + k are destroyed here, and any memory used by v + k is freed
      

      【讨论】:

      • 此功能在 C++ 中被广泛使用,通过 Resource Acquisition Is Initialization (RAII) 习惯用法自动管理资源获取和释放。
      • 只是一个小的措辞问题:每个变量在其作用域/生命周期结束时都会被销毁,所以实际上,obj*b 是“被销毁的”。它的析构函数什么都不做,因此new obj 不会被删除。只需更改指针的类型,即。 smart_ptr<obj> 有一个析构函数,没有范围变化,但是对象被删除了。
      【解决方案4】:

      自动堆栈是分配在当前方法堆栈上的变量。设计一个可以充当 Stack 自动的类背后的想法是,应该可以通过一次调用完全初始化它并用另一个调用销毁它。析构函数必须释放对象分配的所有资源,并且其构造函数返回一个已完全初始化并准备好使用的对象。与复制操作类似——该类应该能够很容易地被复制,这是功能齐全且独立的。

      此类的用法应该类似于原始 int、float 等的使用方式。你定义它们(最终给它们一些初始值),然后传递它们,最后让编译器进行清理。

      【讨论】:

        【解决方案5】:

        C++ 中的变量既可以在堆栈上声明,也可以在堆上声明。当您在 C++ 中声明一个变量时,它会自动进入堆栈,除非您显式使用 new 运算符(它进入堆)。

        MyObject x = MyObject(params); // onto the stack
        
        MyObject * y = new MyObject(params); // onto the heap
        

        这对内存的管理方式有很大的影响。当变量在堆栈上声明时,它将在超出范围时被释放。在对象上显式调用 delete 之前,堆上的变量不会被销毁。

        【讨论】:

        • 其实你要小心那里。尽管我们都知道全局数据不好,但不要忘记全局/静态数据所在的数据(已初始化)和 BSS(未初始化)段。
        猜你喜欢
        • 2011-05-09
        • 1970-01-01
        • 2023-03-09
        • 2010-09-15
        • 2011-05-30
        • 2015-05-14
        • 1970-01-01
        相关资源
        最近更新 更多