到目前为止,我一直在用Java编写程序。所以当我开始使用C ++时,首先想到的是如何破坏/删除/完成我不再需要的对象。
使用Java我曾经将它们设置为null
所以垃圾收集器正在处理它。
但是,我不知道C ++的价值。我发现这篇文章http://en.wikipedia.org/wiki/Comparison_of_Java_and_C%2B%2B解决了我的大部分问题。但仍有一些我不明白的事情。
1)在Java中,有一种方法可以强制垃圾收集器在现场清理(这并不总是有用,因为它在运行之前等待一些垃圾堆叠起来)。有没有办法用C ++做到这一点?
2)(C ++)也与上述相反,我怎样才能使对象处于“标记为删除”的状态,并且程序决定何时清理它(如Java)? / p>
3)(C ++)我应该迫使垃圾收集器在现场清理(我很确定这不是正确的方法,但我要求确定)?
如果你能给出一个代码触发器的小代码示例,我会赞美它。
答案 0 :(得分:6)
1)如果您的对象处于自动存储中,您可以限制其范围:
{
X x;
//...
} //x gets destructed here
如果在动态存储中,则在完成后删除它们:
X* x = new X;
//...
delete x; //x gets destructed
2)你不能(至少以干净的方式)。您必须指示C ++何时删除对象,即使该指令包含结束括号。 (请参阅第一个代码段)
3)C ++中没有垃圾收集器。看两个片段。您要么必须显式删除对象(如果在动态存储中),要么在自动存储中自动删除它们(但不是垃圾收集器)。
值得研究的是智能指针(那里有大量的实现),但这也不是垃圾收集器。它只是为您节省了管理内存的麻烦。但它与Java无关。
答案 1 :(得分:4)
C ++在这方面与Java非常不同,所以这里有一个简要概述:
分配:为对象留出内存
结构:准备使用该物体。
破坏:物体“完成”一切并自行拆解。
解除分配:将内存返回给系统。
int main() {
int myint; //automatic int object is allocated and constructed
//stuff
} // when main ends, automatic int object is destroyed and deallocated
int main() {
int* mypointer; //automatic pointer object is allocated and constructed
mypointer = new int; //dynamic int object is allocated and constructed
//stuff
delete mypointer; //dynamic int object is destroyed and deallocated
} // when main ends, automatic pointer object is destroyed and deallocated
// note: Pointers to _not_ delete the object they point to.
class myclass {
//members
public:
myclass() {} //this is the default constructor
myclass(const myclass& rhs) {} //this is the copy constructor
myclass& operator=(const myclass& rhs) {return *this} //this is the assignment operator
~myclass() {} //this is the destructor
};
当一个函数结束时,函数本身的所有变量(我们称之为自动变量)都会调用它们的析构函数,然后自动释放它们。这意味着对于函数本地的对象,它们会自动清除函数结束的 instant 。这也适用于一个类的成员。当它被销毁时,它的每个成员都将被自动销毁。这意味着大多数析构函数都是空的。
如果手动分配内容(使用new
关键字),则必须使用delete
关键字手动销毁和取消分配内容。当你调用delete
时,它会在那里销毁(并解除分配)然后,并且在完成之前不会继续。如果您忘记了,它将无法获得DEALLOCATED(尽管某些操作系统将在您的程序结束时解除分配)。
由于人们会犯错误,因此在需要动态对象时要做的“正确”事情是:
int main() {
std::unique_ptr<myclass> myptr = new myclass(); //allocate and construct
} //both the unique_ptr and the dynamic object are destroyed and deallocated
并且unique_ptr
非常聪明,能够自动清理它指向的内容,让您免于更大的顾虑。
C ++执行此操作的原因是因为如果您有一个表示该文件的对象F
,它可能对该文件具有独占锁定。在C ++中,一旦F
被销毁,您就可以立即创建使用该文件的对象G
。在Java中,无法保证finalizer
将永远运行,这意味着文件可能会在程序结束前保持锁定状态。 (不太可能,但可能)
答案 2 :(得分:3)
C ++中没有垃圾收集器。你应该自己编写和运行析构函数。在C ++中,忘记运行析构函数是一个常见的错误。
如果您的对象已分配new
,则应使用delete
将其删除。因此,new
调用contructor,而delete
调用析构函数。
myclass *p = new myclass();
// do something
delete p;
这称为动态对象分配。
如果您的对象是“正常”定义的,当超出范围时它将自动被破坏。
myclass a;
// do something
// will destructed when }
这称为自动对象分配。
P.S。您也没有在Java中分配空值,因为垃圾收集器是为了不打扰删除对象而发明的。
答案 3 :(得分:1)
C ++中的垃圾收集始终是即时的。没有单独的垃圾收集器;删除对象时,它会立即删除当前线程。它看起来像这样:
MyObject* foo = new MyObject();
...
delete foo;
有可用于C ++的垃圾收集框架,您还可以查看智能指针,这也是垃圾收集的一种形式。
注意下面的James评论 - 对象的析构函数和操作符删除总是立即被调用,但是它是依赖于实现的,关于内存是否可以立即可用。
答案 4 :(得分:1)
C ++使用RAII(资源获取是初始化)编程习惯,没有什么比在Java中称为垃圾收集器或在Objective-C 2中称为AutoZone的自动内存管理。因此,正确的实例清理很容易变得复杂。回答你的问题:
广告1:C ++中没有GC,因此您必须手动删除对象或使用引用计数技术或更好的智能指针,它们现在是C ++ 11标准的一部分,但据我所知,它是尚未在任何C ++编译器中提供。现在,您可以使用Boost库中的智能指针模板:http://www.boost.org/doc/libs/1_48_0/libs/smart_ptr/smart_ptr.htm。新的C ++标准直接采用了Boost实现,因此在不久的将来切换到新标准时将没有问题(MSVC 2012将实现C ++ 11支持)。
ad 2:无法标记,只需在右侧“手动”删除它,或将此任务保留在智能指针上。
广告3:不适用。
最后,始终有最简单的选项 - 不要在堆上分配对象,这意味着动态。在Java中没有这种可能性,但在C ++中有。 我甚至读过一些关于C ++编程的Stroustrup(C ++的创建者)的好书,在C ++创建时,不推荐这样的动态分配。他表示:要让RAII正常工作,一定不能进行动态分配 - 今天听起来很奇怪,但这就是Stroustrup所写的内容,它不是我的头脑,我个人动态分配几乎所有人都做的事情......
静态分配的主要原因是一旦超出范围就会删除对象,因此根本不必担心异常安全和清理。如果您动态分配实例,则如果实例离开当前范围,则不会自动删除它 - 如果您没有手动删除实例,则会发生内存泄漏。考虑一下简单的try-catch块:
try
{
Class *instance = new Class;
//some error
}
catch(...)
{
//error caught - current execution is terminated immediately, instance is no deleted - memory leak.
}
我在Java中有一个始终被调用的finally语句,因此您可以在抛出异常时执行必要的清理。但是在C ++中你遇到麻烦... 除非你使用提到的智能指针或一些非常类似的技术。当使用智能指针时你不必再担心清理了(在实践中并不完全正确) ,但你的生活肯定会更容易,你的代码也会减少错误。)