一、拷贝构造函数基础
1.1 拷贝构造函数的定义和声明
class CopyConstructorBasics {
private:
int* data;
size_t size;
std::string name;
public:
// 标准拷贝构造函数声明
CopyConstructorBasics(const CopyConstructorBasics& other);
// 其他可能的声明形式(不常用)
// CopyConstructorBasics(CopyConstructorBasics& other); // 非const引用
// CopyConstructorBasics(const CopyConstructorBasics& other, int = 0); // 带默认参数
// CopyConstructorBasics(volatile const CopyConstructorBasics& other); // volatile
// 普通构造函数
CopyConstructorBasics(size_t s, const std::string& n)
: data(new int[s]()), size(s), name(n) {
std::cout << "Normal constructor\n";
}
// 析构函数
~CopyConstructorBasics() {
delete[] data;
std::cout << "Destructor for " << name << "\n";
}
};
// 拷贝构造函数实现
CopyConstructorBasics::CopyConstructorBasics(const CopyConstructorBasics& other)
: size(other.size)
, name(other.name + "_copy") {
std::cout << "Copy constructor\n";
// 深拷贝
data = new int[size];
std::copy(other.data, other.data + size, data);
}
1.2 拷贝构造函数的调用时机
class CopyScenarios {
std::string name;
public:
CopyScenarios(const std::string& n) : name(n) {
std::cout << "Constructor: " << name << "\n";
}
CopyScenarios(const CopyScenarios& other) : name(other.name + "_copy") {
std::cout << "Copy constructor: " << name << "\n";
}
~CopyScenarios() {
std::cout << "Destructor: " << name << "\n";
}
static void demonstrateCopyScenarios() {
std::cout << "=== Scenario 1: Direct initialization ===\n";
CopyScenarios obj1("obj1");
CopyScenarios obj2(obj1); // 拷贝构造
std::cout << "\n=== Scenario 2: Copy initialization ===\n";
CopyScenarios obj3 = obj1; // 拷贝构造(不是赋值)
std::cout << "\n=== Scenario 3: Function parameter (pass by value) ===\n";
auto func = [](CopyScenarios param) { // 参数通过拷贝构造传入
std::cout << "Inside function\n";
};
func(obj1);
std::cout << "\n=== Scenario 4: Return by value ===\n";
auto createObject = []() -> CopyScenarios {
CopyScenarios temp("temp");
return temp; // 可能触发拷贝构造(或被优化)
};
CopyScenarios obj4 = createObject();
std::cout << "\n=== Scenario 5: Container operations ===\n";
std::vector<CopyScenarios> vec;
vec.reserve(3); // 预分配避免重新分配
vec.push_back(obj1); // 拷贝构造
vec.push_back(CopyScenarios("temp2")); // 可能移动构造
std::cout << "\n=== Scenario 6: Exception throwing ===\n";
try {
throw obj1; // 拷贝构造异常对象
} catch (CopyScenarios e) { // 再次拷贝构造
std::cout << "Caught exception\n";
}
std::cout << "\n=== End of demonstration ===\n";
}
};
二、深拷贝与浅拷贝
2.1 浅拷贝的问题
class ShallowCopyProblem {
private:
int* data;
size_t size;
public:
ShallowCopyProblem(size_t s) : size(s), data(new int[s]) {
std::cout << "Constructor: allocated " << size << " ints\n";
}
// 编译器生成的默认拷贝构造函数(浅拷贝)
// ShallowCopyProblem(const ShallowCopyProblem& other)
// : data(other.data) // 危险!只拷贝指针
// , size(other.size) {}
~ShallowCopyProblem() {
delete[] data; // 双重删除问题!
std::cout << "Destructor: freed memory\n";
}
static void demonstrateProblem() {
ShallowCopyProblem obj1(10);
{
ShallowCopyProblem obj2(obj1); // 浅拷贝
// obj1和obj2的data指向同一块内存
} // obj2析构,删除data
// obj1的data现在是悬空指针!
// obj1析构时会再次删除,导致未定义行为
}
};
2.2 深拷贝实现
class DeepCopy {
private:
int* data;
size_t size;
size_t capacity;
std::string* names;
// 嵌套类也需要深拷贝
class Node {
public:
int value;
Node* next;
Node(int v) : value(v), next(nullptr) {}
// Node的深拷贝
Node* deepCopy() const {
Node* newNode = new Node(value);
if (next) {
newNode->next = next->deepCopy();
}
return newNode;
}
};
Node* head;
public:
DeepCopy(size_t s)
: size(s)
, capacity(s * 2)
, data(new int[capacity]())
, names(new std::string[size])
, head(nullptr) {
std::cout << "Constructor\n";
}
// 深拷贝构造函数
DeepCopy(const DeepCopy& other)
: size(other.size)
, capacity(other.capacity) {
std::cout << "Deep copy constructor\n";
// 1. 拷贝动态数组
data = new int[capacity];
std::copy(other.data, other.data + size, data);
// 2. 拷贝字符串数组
names = new std::string[size];
std::copy(other.names, other.names + size, names);
// 3. 拷贝链表
if (other.head) {
head = other.head->deepCopy();
} else {
head = nullptr;
}
}
~DeepCopy() {
delete[] data;
delete[] names;
// 删除链表
while (head) {
Node* temp = head;
head = head->next;
delete temp;
}
std::cout << "Destructor\n";
}
// 辅助函数:添加节点
void addNode(int value) {
Node* newNode = new Node(value);
newNode->next = head;
head = newNode;
}
};
2.3 智能指针与拷贝
class SmartPointerCopy {
private:
// unique_ptr:独占所有权,不能拷贝
std::unique_ptr<int> uniqueData;
// shared_ptr:共享所有权,可以拷贝
std::shared_ptr<int> sharedData;
// 自定义删除器的shared_ptr
std::shared_ptr<int[]> arrayData;
// weak_ptr:弱引用
std::weak_ptr<int> weakData;
public:
SmartPointerCopy()
: uniqueData(std::make_unique<int>(42))
, sharedData(std::make_shared<int>(100))
, arrayData(new int[10], std::default_delete<int[]>()) {
weakData = sharedData;
}
// 拷贝构造函数
SmartPointerCopy(const SmartPointerCopy& other)
: uniqueData(other.uniqueData ?
std::make_unique<int>(*other.uniqueData) : nullptr) // 深拷贝
, sharedData(other.sharedData) // 共享所有权
, arrayData(other.arrayData) // 共享所有权
, weakData(other.weakData) { // 弱引用拷贝
std::cout << "Copy constructor\n";
std::cout << "Shared count: " << sharedData.use_count() << "\n";
}
// 演示不同的拷贝策略
void demonstrateCopyStrategies() {
// 策略1:深拷贝(独占资源)
class DeepCopyStrategy {
std::unique_ptr<std::vector<int>> data;
public:
DeepCopyStrategy() : data(std::make_unique<std::vector<int>>()) {}
DeepCopyStrategy(const DeepCopyStrategy& other)
: data(std::make_unique<std::vector<int>>(*other.data)) {}
};
// 策略2:共享资源(引用计数)
class SharedStrategy {
std::shared_ptr<std::vector<int>> data;
public:
SharedStrategy() : data(std::make_shared<std::vector<int>>()) {}
SharedStrategy(const SharedStrategy& other) = default; // 共享
};
// 策略3:写时拷贝(COW)
class COWStrategy {
struct Data {
std::vector<int> vec;
mutable std::mutex mtx;
};
std::shared_ptr<Data> data;
public:
COWStrategy() : data(std::make_shared<Data>()) {}
COWStrategy(const COWStrategy& other) : data(other.data) {}
void modify(size_t index, int value) {
if (data.use_count() > 1) {
// 需要拷贝
data = std::make_shared<Data>(*data);
}
std::lock_guard<std::mutex> lock(data->mtx);
data->vec[index] = value;
}
};
}
};
三、拷贝构造函数的特殊情况
3.1 禁用拷贝构造
class NoCopy {
private:
std::unique_ptr<int> data;
public:
NoCopy() : data(std::make_unique<int>(42)) {}
// 方法1:删除拷贝构造函数(C++11)
NoCopy(const NoCopy&) = delete;
NoCopy& operator=(const NoCopy&) = delete;
// 方法2:私有化(C++98方式,不推荐)
// private:
// NoCopy(const NoCopy&);
// NoCopy& operator=(const NoCopy&);
};
// 单例模式示例
class Singleton {
private:
static Singleton* instance;
Singleton() = default;
// 禁止拷贝
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton& getInstance() {
static Singleton instance; // C++11保证线程安全
return instance;
}
};
// 使用基类禁用拷贝
class NonCopyable {
protected:
NonCopyable() = default;
~NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator=(const NonCopyable&) = delete;
};
class MyClass : private NonCopyable {
// 自动继承不可拷贝特性
};
3.2 拷贝构造函数与继承
class Base {
protected:
int* baseData;
std::string baseName;
public:
Base(const std::string& name)
: baseData(new int(100))
, baseName(name) {
std::cout << "Base constructor\n";
}
// 基类拷贝构造函数
Base(const Base& other)
: baseData(new int(*other.baseData))
, baseName(other.baseName + "_base_copy") {
std::cout << "Base copy constructor\n";
}
virtual ~Base() {
delete baseData;
std::cout << "Base destructor\n";
}
};
class Derived : public Base {
private:
double* derivedData;
std::vector<int> vec;
public:
Derived(const std::string& name)
: Base(name)
, derivedData(new double(3.14))
, vec{1, 2, 3} {
std::cout << "Derived constructor\n";
}
// 派生类拷贝构造函数
Derived(const Derived& other)
: Base(other) // 显式调用基类拷贝构造函数
, derivedData(new double(*other.derivedData))
, vec(other.vec) {
std::cout << "Derived copy constructor\n";
}
~Derived() {
delete derivedData;
std::cout << "Derived destructor\n";
}
};
// 切片问题
class SlicingProblem {
public:
static void demonstrate() {
Derived d("derived");
// 对象切片
Base b = d; // 只拷贝Base部分,丢失Derived部分
// 正确做法:使用指针或引用
Base* ptr = new Derived(d); // 完整拷贝
Base& ref = d; // 引用原对象
delete ptr;
}
};
3.3 拷贝构造函数与异常安全