在我的互联网浏览中,我遇到了this post,其中包含了这个
“(写得好)C ++很棒 长度使堆栈自动化 对象工作“就像”原语, 正如Stroustrup建议的那样 “像投注那样做”。这需要一个 更加坚持 面向对象的原则 发展:你的班级不对 直到它“像”一个int, 遵循“三法则”即 保证它可以(就像一个int) 被创建,复制和正确 被自动摧毁。“
我已经完成了一些C和C ++代码,但只是顺便说一下,从来没有任何严肃的事情,但我只是好奇,这究竟意味着什么?
有人能举个例子吗?
答案 0 :(得分:12)
堆栈对象由编译器自动处理。
当保留范围时,它将被删除。
{
obj a;
} // a is destroyed here
对“newed”对象执行相同操作时会出现内存泄漏:
{
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
答案 1 :(得分:2)
除了其他答案:
C ++语言实际上有auto
关键字来显式声明对象的存储类。当然,这完全是不必要的,因为这是局部变量的隐含存储类,不能在任何地方使用。与auto
相反的是static
(本地和全球)。
以下两个声明是等效的:
int main() {
int a;
auto int b;
}
因为关键字完全无用,它实际上会在下一个C ++标准(“C ++ 0x”)中被回收并获得一个新含义,即它允许编译器从其初始化中推断出变量类型(如{在C#中{1}}:
var
答案 2 :(得分:1)
C ++中的变量既可以在堆栈上声明,也可以在堆上声明。当你在C ++中声明一个变量时,它会自动进入堆栈,除非你明确地使用new运算符(它进入堆)。
MyObject x = MyObject(params); // onto the stack
MyObject * y = new MyObject(params); // onto the heap
这对内存的管理方式产生了很大的影响。当在堆栈上声明变量时,它将在超出范围时被释放。在对象上显式调用delete之前,不会销毁堆上的变量。
答案 3 :(得分:1)
Stack automatic是在当前方法的堆栈上分配的变量。设计一个可以充当Stack自动的类的想法是,应该可以通过一次调用完全初始化它并用另一个调用将其销毁。析构函数必须释放对象分配的所有资源,并且其构造函数返回一个已完全初始化并可供使用的对象。类似地,对于复制操作 - 该类应该能够容易地进行复制,这些复制是完全功能和独立的。
此类的用法应与使用原始int,float等的方式类似。你定义它们(最终给它们一些初始值),然后传递它们,最后让编译器进行清理。
答案 4 :(得分:1)
如果我错了,请纠正我,但我认为复制操作不是强制性的,以充分利用自动堆栈清理。 例如,考虑一个经典的MutexGuard对象,它不需要复制操作作为堆栈自动使用,或者它是否有用?