题
在浏览互联网时,我遇到了 这个帖子, ,其中包括这个
“(写得很好)C ++竭尽全力使堆栈自动对象起作用”,就像“原始”一样,如Stroustrup的建议所反映的“像INT一样执行”。这需要更大程度地遵守面向对象的发展原则:您的班级直到遵循“三个规则”(保证它可以(就像int一样)被创建,复制并正确地被销毁为堆栈自动变速箱)的“规则”之后,您的班级不正确。”
我写了一些 C 和 C++ 代码,但只是顺便写了一些,从来没有做过任何严肃的事情,但我只是很好奇,它到底意味着什么?
有人可以举个例子吗?
解决方案
堆栈对象由编译器自动处理。
当离开范围时,它被删除。
{
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”)中被回收并获得新的含义,即它让编译器从变量的初始化中推断出变量类型(例如 var
在 C# 中):
auto a = std::max(1.0, 4.0); // `a` now has type double.
C++ 中的变量可以在堆栈或堆上声明。当您在 C++ 中声明变量时,它会自动进入堆栈,除非您显式使用 new 运算符(它进入堆)。
MyObject x = MyObject(params); // onto the stack
MyObject * y = new MyObject(params); // onto the heap
这对内存管理方式产生了很大的影响。当一个变量在堆栈上声明时,当它超出范围时,它将被释放。在对象上显式调用 delete 之前,堆上的变量不会被销毁。
自动堆栈是在当前方法的堆栈上分配的变量。设计一个可以充当堆栈自动功能的类背后的想法是,应该可以通过一次调用完全初始化它,并通过另一次调用销毁它。析构函数必须释放对象分配的所有资源,并且其构造函数返回一个已完全初始化并可供使用的对象,这一点至关重要。类似地,对于复制操作 - 类应该能够轻松地进行复制,其功能齐全且独立。
此类的用法应该类似于原始 int、float 等的用法。被使用。您定义它们(最终给它们一些初始值),然后传递它们,最后让编译器进行清理。
如果我错了,请纠正我,但我认为复制操作对于充分利用自动堆栈清理并不是强制性的。例如,考虑一个经典的 MutexGuard 对象,它不需要复制操作即可作为堆栈自动使用,或者是吗?