成员变量在调用析构函数之前会消失吗?

时间:2018-08-02 20:30:38

标签: c++

我正在运行此代码来确定在将对象重新分配给对象之前或之后销毁了哪个对象。但是我没有得到预期的输出。变量id通过包含的print函数可以正确打印,但是在析构函数打印时,它会失败并带有其他一些数字,并且这两个对象都相同。为什么会这样?

#include <iostream>
#include <string>

class A {
    static int _idx;
    int id;
public:
    A()
    {
    std::cout << "Default constructor" << std::endl;
    id = _idx;
    _idx++;
    }
    A(std::string&& str)
    { 
    id = _idx;
    _idx++;
    std::cout << str << std::endl;
    }
    void print()
    {
    std::cout << id << std::endl;
    }
    ~A()
    {
    std::cout << id << std::endl;
    }
};

int A::_idx = 0;



int main(void)
{
    A a;
    a.print();
    a = std::string("World");
 }

输出:

Default constructor
0
World
1
1

编辑:删除了草率的代码并添加了示例输出以进行澄清

4 个答案:

答案 0 :(得分:6)

不要显式调用析构函数。只需让变量超出范围即可。

A超出范围时,首先要运行的是析构函数主体,其次是类中成员变量的所有析构函数,其构造顺序相反。,然后针对所有基类继续进行该过程。

(成员变量按照它们在类声明中出现的顺序构造。)

在您的代码中,因为构造了A的2个实例,所以析构函数被调用了两次;请注意,编译器生成的赋值运算符实际上是导致id的值在销毁点处为1的事物。

答案 1 :(得分:5)

标题问题:

  

成员变量在调用析构函数之前会消失吗?

答案是。所有成员变量都在析构函数体内有效。

帖子中的问题:

  

已包含的打印功能正确打印了变量id,但是在析构函数打印时,变量id失败,并带有其他一些数字,并且两个对象的两个变量相同。为什么会这样?

这个问题可以追溯到这行:

a = std::string("World");

这将调用该类的重载构造函数以创建一个临时对象,并将该临时对象分配给a。这里的问题是构造函数的实现。

它曾经是

A(std::string&& str)
{ 
   std::cout << str << std::endl;
}

构造函数将成员变量保留为未初始化状态。因此,成员变量的值可以是任何值。

现在您将其更改为

A(std::string&& str)
{ 
   id = _idx;
  _idx++;
   std::cout << str << std::endl;
}

您的程序将以可预测的方式运行。

为什么最后的输出行是这样?

考虑这条线

    a = std::string("World");

等效于:

  1. 构造一个临时对象。 (其id为1)
  2. 将临时对象分配给a。现在a.id是1。
  3. 销毁临时对象。析构函数在临时实例上被调用。您将获得输出1

函数返回时,a被破坏。析构函数在a上得到调用。由于a.id设置为1,因此输出为1。

答案 2 :(得分:2)

当对象需要死亡时,调用析构函数。析构函数运行后,成员变量以声明的相反顺序被破坏。析构函数首先运行。

答案 3 :(得分:1)

  

两个对象的两者相同。为什么会这样?

因为这一行。

a = std::string("World");

这会构造一个{strong>秒的A ,其中包含id = 1,并将其分配给第一个A,使之{{1} }也id

1赋值运算符。意思是“把左边的东西变成右边的东西”。