当C ++中的对象被破坏时,这是什么意思?我是否必须手动销毁它们,因为没有垃圾收集器?例外如何发挥作用?
<子> (注意:这是Stack Overflow's C++ FAQ的一个条目。如果您想批评在此表单中提供常见问题解答的想法,那么the posting on meta that started all this就是这样做的地方。在C++ chatroom中监控了这个问题,首先是FAQ的想法,所以你的答案很可能会被那些提出想法的人阅读。) 子>
答案 0 :(得分:78)
答案 1 :(得分:35)
当对象生命周期结束并被销毁时,会自动调用对象的析构函数。你通常不应该手动调用它。
我们将使用此对象作为示例:
class Test
{
public:
Test() { std::cout << "Created " << this << "\n";}
~Test() { std::cout << "Destroyed " << this << "\n";}
Test(Test const& rhs) { std::cout << "Copied " << this << "\n";}
Test& operator=(Test const& rhs) { std::cout << "Assigned " << this << "\n";}
};
C ++中有三种(C ++ 11中有四种)不同类型的对象,对象的类型定义了对象的生命周期。
这些是最简单的,等同于全局变量。这些对象的生命周期(通常)是应用程序的长度。这些(通常)是在我们退出main之后(在创建的主顺序中)之前构建的。
Test global;
int main()
{
std::cout << "Main\n";
}
> ./a.out
Created 0x10fbb80b0
Main
Destroyed 0x10fbb80b0
注1:还有另外两种静态存储持续时间对象。
就生命周期而言,这些意义和目的与全局变量相同。
这些是懒惰创建的静态存储持续时间对象。它们是在第一次使用时创建的(在C ++ 11的线程安全庄园中)。与其他静态存储持续时间对象一样,它们在应用程序结束时被销毁。
这些是最常见的对象类型,99%的情况下你应该使用它们。
这是三种主要类型的自动变量:
当退出一个函数/块时,在该函数/块内声明的所有变量都将被销毁(按照创建的相反顺序)。
int main()
{
std::cout << "Main() START\n";
Test scope1;
Test scope2;
std::cout << "Main Variables Created\n";
{
std::cout << "\nblock 1 Entered\n";
Test blockScope;
std::cout << "block 1 about to leave\n";
} // blockScope is destrpyed here
{
std::cout << "\nblock 2 Entered\n";
Test blockScope;
std::cout << "block 2 about to leave\n";
} // blockScope is destrpyed here
std::cout << "\nMain() END\n";
}// All variables from main destroyed here.
> ./a.out
Main() START
Created 0x7fff6488d938
Created 0x7fff6488d930
Main Variables Created
block 1 Entered
Created 0x7fff6488d928
block 1 about to leave
Destroyed 0x7fff6488d928
block 2 Entered
Created 0x7fff6488d918
block 2 about to leave
Destroyed 0x7fff6488d918
Main() END
Destroyed 0x7fff6488d930
Destroyed 0x7fff6488d938
成员变量的生命周期绑定到拥有它的对象。当业主的寿命结束时,其所有成员的寿命也将结束。因此,您需要查看遵守相同规则的所有者的生命周期。
注意:成员总是在所有者之前按照相反的创建顺序销毁。
这些是作为表达式结果创建但未分配给变量的对象。临时变量就像其他自动变量一样被销毁。只是它们范围的结尾是创建它们的语句的结尾(这通常是';')。
std::string data("Text.");
std::cout << (data + 1); // Here we create a temporary object.
// Which is a std::string with '1' added to "Text."
// This object is streamed to the output
// Once the statement has finished it is destroyed.
// So the temporary no longer exists after the ';'
注意:有些情况下可以延长临时寿命 但这与这个简单的讨论无关。当你明白这个文件对你来说是第二天性的时候,在它延长之前,暂时的生命不是你想做的事情。
这些对象具有动态生命周期,使用new
创建,并通过调用delete
销毁。
int main()
{
std::cout << "Main()\n";
Test* ptr = new Test();
delete ptr;
std::cout << "Main Done\n";
}
> ./a.out
Main()
Created 0x1083008e0
Destroyed 0x1083008e0
Main Done
对于来自垃圾收集语言的开发人员来说,这看起来很奇怪(管理对象的生命周期)。但问题并不像看起来那么糟糕。在C ++中直接使用动态分配的对象是不常见的。我们有管理对象来控制他们的生命周期。
与大多数其他GC收集的语言最接近的是std::shared_ptr
。这将跟踪动态创建的对象的用户数量,当所有这些对象都消失后,将自动调用delete
(我认为这是普通Java对象的更好版本)。
int main()
{
std::cout << "Main Start\n";
std::shared_ptr<Test> smartPtr(new Test());
std::cout << "Main End\n";
} // smartPtr goes out of scope here.
// As there are no other copies it will automatically call delete on the object
// it is holding.
> ./a.out
Main Start
Created 0x1083008e0
Main Ended
Destroyed 0x1083008e0
这些是该语言的新功能。它们非常类似于静态存储持续时间对象。但是,与他们所居住的应用程序生活相同的生命,只要它们与执行的线程相关联。