C ++-"自动堆栈"是什么意思?

时间:2020-03-05 18:43:50  来源:igfitidea点击:

在互联网上浏览时,我遇到了这篇文章,其中包括

"(Well written) C++ goes to great
  lengths to make stack automatic
  objects work "just like" primitives,
  as reflected in Stroustrup's advice to
  "do as the ints do". This requires a
  much greater adherence to the
  principles of Object Oriented
  development: your class isn't right
  until it "works like" an int,
  following the "Rule of Three" that
  guarantees it can (just like an int)
  be created, copied, and correctly
  destroyed as a stack automatic."

我已经做了一些C和C ++代码,但是顺便说一句,从不认真,但是我很好奇,这到底意味着什么?

有人可以举个例子吗?

解决方案

回答

C ++中的变量可以在堆栈或者堆上声明。在C ++中声明变量时,除非我们显式使用new运算符(将其放入堆),否则它将自动进入堆栈。

MyObject x = MyObject(params); // onto the stack

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

这在内存管理方式上有很大的不同。在堆栈上声明变量时,超出范围时将释放该变量。在对象上显式调用delete之前,不会破坏堆上的变量。

回答

自动堆栈是在当前方法的堆栈上分配的变量。设计一个可以自动执行Stack的类的想法是,应该可以通过一个调用将其完全初始化,而在另一个调用中将其销毁。析构函数必须释放该对象分配的所有资源,并且其构造函数返回已完全初始化并可以使用的对象,这一点至关重要。类似地,对于复制操作,该类应该能够轻松地制作成具有完全功能且独立的副本。

此类的用法应类似于原始int,float等的用法。我们定义它们(最终给它们一些初始值),然后传递它们,最后将编译器交给清理人员。

回答

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

保留范围后,将其删除。

{
   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 ++语言实际上具有auto关键字来显式声明对象的存储类。当然,这完全没有必要,因为这是局部变量的隐含存储类,不能在任何地方使用。 " auto"的相反是" static"(本地和全局)。

以下两个声明是等效的:

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

因为该关键字完全没有用,所以实际上它将在下一个C ++标准(C ++ 0x)中回收并得到新的含义,即,它使编译器从其初始化中推断变量类型(如C#中的var)。 :

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

回答

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