我正在运行此代码来确定在将对象重新分配给对象之前或之后销毁了哪个对象。但是我没有得到预期的输出。变量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
编辑:删除了草率的代码并添加了示例输出以进行澄清
答案 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");
等效于:
id
为1)a
。现在a.id
是1。函数返回时,a
被破坏。析构函数在a
上得到调用。由于a.id
设置为1,因此输出为1。
答案 2 :(得分:2)
当对象需要死亡时,调用析构函数。析构函数运行后,成员变量以声明的相反顺序被破坏。析构函数首先运行。
答案 3 :(得分:1)
两个对象的两者相同。为什么会这样?
因为这一行。
a = std::string("World");
这会构造一个{strong>秒的A
,其中包含id = 1
,并将其分配给第一个A
,使之{{1} }也id
。
1
是赋值运算符。意思是“把左边的东西变成右边的东西”。