我正在从
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)而不是复制.但我把它留下来保持清单简单.