#include <iostream>
#include <memory>
class Base {
public:
virtual ~Base() {
std::cout << "Base destructor" << std::endl;
}
};
class Derived : public Base {
private:
int* data;
public:
Derived() : data(new int(42)) {
std::cout << "Derived constructor" << std::endl;
}
Derived(const Derived& other) : data(new int(*other.data)) {
std::cout << "Derived copy constructor" << std::endl;
}
Derived(Derived&& other) noexcept : data(other.data) {
other.data = nullptr;
std::cout << "Derived move constructor" << std::endl;
}
Derived& operator=(const Derived& other) {
if (this != &other) {
delete data;
data = new int(*other.data);
}
std::cout << "Derived copy assignment operator" << std::endl;
return *this;
}
Derived& operator=(Derived&& other) noexcept {
if (this != &other) {
delete data;
data = other.data;
other.data = nullptr;
}
std::cout << "Derived move assignment operator" << std::endl;
return *this;
}
~Derived() {
delete data;
std::cout << "Derived destructor" << std::endl;
}
virtual void print() const {
if (data) {
std::cout << "Data in Derived: " << *data << std::endl;
} else {
std::cout << "Data in Derived is nullptr" << std::endl;
}
}
};
int main() {
Derived d1;
Derived d2 = std::move(d1);
d2.print();
d1.print();
std::unique_ptr<Base> basePtr1 = std::make_unique<Derived>();
std::unique_ptr<Base> basePtr2 = std::move(basePtr1);
if (basePtr1) {
basePtr1->print();
} else {
std::cout << "basePtr1 is nullptr after move" << std::endl;
}
if (basePtr2) {
basePtr2->print();
}
return 0;
}
内存管理
- 移动构造函数:在
Derived(Derived&& other) noexcept
中,将other
的data
指针直接赋值给当前对象,并将other.data
置为nullptr
,这样就避免了重复分配内存,实现了资源的转移。
- 移动赋值运算符:在
Derived& operator=(Derived&& other) noexcept
中,先释放当前对象的资源(delete data
),然后将other
的data
指针赋值过来,并将other.data
置为nullptr
。
虚函数调用
- 通过基类指针:当使用
std::unique_ptr<Base>
来管理Derived
对象,并进行std::move
操作时,虚函数调用仍然能够正确执行。如代码中basePtr2->print()
会调用Derived
类的print
函数,因为print
是虚函数,动态绑定机制会根据对象的实际类型来调用正确的函数。
- 对象状态:移动操作后,源对象(如
d1
)处于有效但可能无意义的状态,这里d1.data
为nullptr
,其print
函数输出相应提示。而目标对象(如d2
)获得了源对象的资源,其print
函数能正常输出数据。