浅拷贝是逐字节拷贝对象的成员变量 ,这里如果成员变量是指针,很明显,只拷贝了指针储存的地址 ,并没有去拷贝指针指向的值。由此引出了C++中的深浅拷贝。拷贝赋值与拷贝构造类似,这里以拷贝构造为例来说明深浅拷贝。
首先,这里我们有一个类,先不写拷贝构造函数:
cpp
#include <iostream>
#include <vector>
class TestClass {
public:
TestClass(int num)
: num_{ 1 },
num_ptr_{ new int(num) }
{
std::cout << "default constructor\n";
}
~TestClass() {
num_ptr_ = nullptr;
std::cout << "destructor\n";
}
private:
int num_;
int* num_ptr_;
};
int main() {
int num{ 1 };
TestClass test_default{ num }; // 默认构造
TestClass test_move{ test_default }; // 拷贝构造
std::cout << "Program finished!\n";
return 0;
}
一个类如果不显示写拷贝构造函数,那么编译器会自动为这个类对象创建一个拷贝构造函数,默认行为是逐字节拷贝对象成员变量,我们看调试结果:

两个对象中num_ptr_地址相同,指向的值相同,这就是浅拷贝。
接着我们补充拷贝构造函数:
cpp
// 拷贝构造
TestClass(const TestClass& other)
: num_{ other.num_ },
num_ptr_{ new int(*other.num_ptr_) }
{
std::cout << "copy constructor\n";
}
然后看调试结果:

两个对象中num_ptr_地址不同,指向的值相同,这就是深拷贝。深拷贝确保了两个对象没有共享同一份数据。
写了拷贝构造函数以后,编译器不再自动生成,而是调用我们写的拷贝构造函数,具体是深拷贝还是浅拷贝取决于我们写的这个拷贝构造函数。如果我们在这个拷贝构造函数中做了浅拷贝,那么实际上最终还是浅拷贝。
最后贴出完整代码:
cpp
#include <iostream>
#include <vector>
class TestClass {
public:
TestClass(int num)
: num_{ 1 },
num_ptr_{ new int(num) }
{
std::cout << "default constructor\n";
}
// 拷贝构造
TestClass(const TestClass& other)
: num_{ other.num_ },
num_ptr_{ new int(*other.num_ptr_) }
{
std::cout << "copy constructor\n";
}
~TestClass() {
num_ptr_ = nullptr;
std::cout << "destructor\n";
}
private:
int num_;
int* num_ptr_;
};
int main() {
int num{ 1 };
TestClass test_default{ num }; // 默认构造
TestClass test_move{ test_default }; // 拷贝构造
std::cout << "Program finished!\n";
return 0;
}