You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于C++构造/析构函数及移动语义的运行结果疑问

问题:为什么std::move操作未触发预期的"Nurse 1 DeCreation"?

我编写了一段测试C++构造函数、析构函数调用顺序的程序,运行后输出与预期不符。执行std::move操作时,我预期会出现"Nurse 1 DeCreation",但实际输出"Nurse 0 DeCreation",不确定当前对象是否被销毁替换,或是误执行了复制而非移动操作。

测试代码

#include <iostream>
#include <utility>


class Doctor {
    public:
    Doctor(){
        std::cout << "Doctor Creation\n";
    }

    ~Doctor(){
        std::cout << "Doctor DeCreation\n";
    }
};


class Nurse{
    public:
    int op = 0;
    Nurse(){
        std::cout << "Nurse Creation\n";
    }

    ~Nurse(){
        std::cout << "Nurse " <<  op << " DeCreation\n";
    }
};

class Hospital{
    private:
        Doctor doc;
        Nurse nurse;
    public:
    Hospital(){
        std::cout << "Hospital Creation\n";
    }
    ~Hospital(){
        std::cout << "Hospital DeCreation\n";
    }

    void operate(){
        std::cout << "Hospital Operation\n";
        nurse.op++;
        std::cout << &this->nurse << " " << nurse.op << "\n";
        reset_hospital();
        std::cout << &this->nurse << " " << nurse.op << "\n";
    }

    void reset_hospital(){
        std::cout << &this->nurse << " " << nurse.op << "\n";
        nurse = std::move(Nurse());
        doc = std::move(Doctor());
    }
};

int main(){
    Hospital hospital;
    hospital.operate();
}

程序输出结果

Doctor Creation
Nurse Creation
Hospital Creation
Hospital Operation
0x7fff2316866c 1
0x7fff2316866c 1
Nurse Creation
Nurse 0 DeCreation
Doctor Creation
Doctor DeCreation
0x7fff2316866c 0
Hospital DeCreation
Nurse 0 DeCreation
Doctor DeCreation

解答

核心原因

nurse = std::move(Nurse())执行的是移动赋值操作,而非销毁原对象后创建新对象。原hospital中的nurse对象内存地址全程未变(从输出的地址可以验证),它不会被销毁,只是被临时对象的内容移动覆盖。

详细执行步骤拆解

  1. 临时对象创建:Nurse()会创建一个临时Nurse对象,此时输出"Nurse Creation",这个临时对象的op初始值为0。
  2. 移动赋值触发:std::move()将临时对象转换为右值引用,触发编译器生成的默认移动赋值运算符。默认移动赋值会把临时对象的op值(0)拷贝给原nurse对象的op,覆盖原本的1。
  3. 临时对象销毁:临时对象完成移动赋值后生命周期结束,触发析构函数,输出"Nurse 0 DeCreation"——这条输出销毁的是临时对象,而非hospital中的原nurse对象。
  4. 原对象的最终销毁:hospital中的nurse对象直到main函数结束、hospital对象生命周期终止时才会被析构,此时它的op已经被修改为0,所以最后输出"Nurse 0 DeCreation"。

额外说明

  • 关于Doctor的操作逻辑完全一致:doc = std::move(Doctor())创建临时Doctor对象,执行默认移动赋值(因为Doctor没有自定义成员,实际无操作),临时对象销毁输出"Doctor DeCreation",原doc对象直到最后才被销毁。
  • 这里没有执行复制操作,确实是移动赋值,但对于int这种简单类型,默认移动赋值和复制赋值的行为一致,都是值拷贝。
  • 原对象(hospital中的nurse和doc)从未被销毁替换,它们的内存地址始终不变,只是成员值被临时对象覆盖。

内容的提问来源于stack exchange,提问作者Nikesh Subedi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 00:15:37