我正在从
java转到c,我试着理解构造/破坏对象.
在java时,我这样做
在java时,我这样做
- Myclass c=createANewObject();
- c=createANewObject();
如果我尝试在c中做同样的事情我会得到奇怪的行为.
- class my_class
- {
- string content;
- time_t t;
- public:
- my_class(string c);
- ~my_class();
- };
- my_class::my_class (string c)
- {
- content=c;
- cout<<"Init -" << content << "-" << t <<endl;
- }
- my_class::~my_class()
- {
- cout<<"Destroyed -" << content << "-" << t <<endl;
- }
- my_class get_new_object(string s)
- {
- my_class c(s);
- return c;
- }
- int main()
- {
- my_class c=get_new_object("A");
- c=get_new_object("B");
- }
而不是得到
- Init -A-
- Init -B-
- destr.A
- destr.B
因为首先我创建A,然后创建B,然后A被销毁,范围结束,因此B被销毁
我明白了
Init -A-1456178128
Init -B-1456178131
Destr.B-1456178131
Destr.B-1456178131
所以我的A被创造而不被摧毁,B ……被摧毁了两次?
解决方法
在Java中,您的代码按以下顺序执行:
>制作一个新对象
>设置引用c以引用该对象
>制作另一个新对象
>从旧对象中释放引用c并使其引用新对象
>旧对象现在没有引用,稍后将被垃圾回收
在C中你的代码是完全不同的.不要被类似的语法所迷惑.在C中,您可以执行与Java代码几乎相同的步骤;通过使用不同的语法.但您实际使用的语法执行以下操作:
>创建一个对象get_new_object :: c(“A”)
>返回该对象的副本
>销毁get_new_object :: c
>通过复制返回的副本使对象main :: c初始化
>销毁返回的副本
>创建一个对象get_new_object :: c(“B”)
>返回该对象的副本
>销毁get_new_object :: c
>通过从返回的对象复制详细信息来更新main :: c
>销毁返回的对象
>(在主要结束时)销毁主:: c
可以通过称为复制省略的过程来优化上述一些副本.如果使用编译器开关来禁用复制省略,则应该看到上述所有步骤,即5个析构函数,2个常规构造函数,以及(如果还为其他特殊函数添加输出),3个复制构造函数和1个赋值运算符.
NB.在C 11中,临时对象可以移入和移出(如果编译器决定不使用elision)而不是复制.但我把它留下来保持清单简单.