浅复制和深复制

题目描述

当一个类的成员变量含有指针时,如果采用默认复制构造函数进行复制,会导致两者指向同一片内存空间,从而导致对其中一个对象指针进行操作会体现在另一对象上。

当成员中含有指针时,朴素地把指针当成普通变量一样直接复制,我们称这种复制方法为“浅复制”。为了解决这一问题,我们可以重新定义复制构造函数,实现“深复制”,请补全下列代码,使得输出符合要求,并思考浅复制和深复制的区别和联系。

关于输入

关于输出

见样例输出

核心技巧

  • 当成员变量涉及指针类型时,不能简单地通过指针变量赋值的方式进行复制。
  • 为解决这一问题,可以通过在复制构造时在复制目标对象重新开辟内存空间,将内容复制过来。

参考答案

#include <iostream>
#include <cstring>
#include <cassert>
using std::cout, std::endl;
class String {
public:
    char* str;
    int len;
    String(const char* s){
        len = strlen(s);
        str = new char[len + 1];
        strcpy(str, s);
    }
    String(const String& s){
        len = s.len;
        str = new char[len + 1];
        strcpy(str, s.str);
    }
    ~String(){
        delete[] str;
    }
};

void pass_by_ref(String& s){
    s.str[0] = 'B';
}
void pass_by_val(String s){
    s.str[0] = 'B';
}
// 内存分配计数器
int allocCount{0};
int main(){
    {
        String str1("Dog");
        const String str2("Dog");
        pass_by_ref(str1);
        pass_by_val(str2);
        cout << str1.len << " " << str1.str << endl;
        cout << str2.len << " " << str2.str << endl;
    }
    assert(allocCount == 0);
}

// 下列代码用于确保你的代码未发生内存泄漏,不用深究
void* operator new[](std::size_t size) {
    if (void* ptr = std::malloc(size)) { allocCount++; return ptr; }
    throw std::bad_alloc{};
}
void operator delete[](void* ptr) {
    allocCount--;
    std::free(ptr);
}