C ++对象销毁

时间:2016-02-22 21:47:30

标签: c++

我从java转到c ++,我尝试理解构造/破坏对象。 在我做的时候

Myclass c=createANewObject();
c=createANewObject();

旧的c被垃圾收集,另一个用同名创建。

如果我尝试在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 ......被摧毁了两次?

3 个答案:

答案 0 :(得分:8)

在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
  • 销毁退回的对象
  • (在主要结尾处)销毁main::c

上述某些副本可能会被称为 copy elision 的过程优化。如果你使用编译器开关来禁用复制省略,你应该看到所有上述步骤,即5个析构函数,2个普通构造函数,以及(如果你还为其他特殊函数添加输出),3个复制构造函数和1个赋值运算符。

NB。在C ++ 11中,临时对象可以移入和移出(如果编译器决定不使用elision)而不是复制。但是我把它留下来以保持清单简单。

答案 1 :(得分:1)

这在某种程度上是编译器和版本(C++11)。

get_new_object创建一个条目,并按值返回。这可能会创建3个对象,2个对象或1个。

3个对象

编译器创建堆栈对象。 这会将复制构造函数转换为临时构造函数。 此临时使用另一个复制构造函数移动到C

2个对象

更聪明的编译器丢失了中间临时。

1个对象

一个非常聪明的编译器意识到只有一个结果很重要。 c++11通过移动构造函数来帮助。

将创建复制/移动构造函数,但不会在代码中进行报告。

析构函数准确描述了创建的对象数量(2)

a / b难题

编译器认为它只需要A. 因此

 init A

创建b时,会创建一个新对象。这是复制到c

Init b

然后b temp被破坏。

Destr b

然后c被销毁

destr b

答案 2 :(得分:1)

<link href="favicon.ico" rel="icon" type="image/x-icon"/>