在我浏览互联网时,我遇到了这个帖子,其中包括这个
“(写得很好)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 之前,不会销毁堆上的变量。
自动堆栈是在当前方法的堆栈上分配的变量。设计一个可以充当 Stack 自动的类背后的想法是,应该可以通过一次调用完全初始化它并用另一个调用销毁它。析构函数必须释放对象分配的所有资源,并且其构造函数返回一个已完全初始化并准备好使用的对象。与复制操作类似——该类应该能够轻松地制作副本,这些副本功能齐全且独立。
此类的用法应该类似于原始 int、float 等的使用方式。您定义它们(最终给它们一些初始值),然后将它们传递给周围,最后让编译器进行清理。
Correct me if i'm wrong, but i think that copy operation is not mandatory to take full advantage of automatic stack cleaning. For example consider a classic MutexGuard object, it doesn't need a copy operation to be useful as stack automatic, or does it ?