物联网/嵌入式工程师
重磅升级:新增硬件电路设计与实战,让你软硬通吃,同级PK无敌!行业风口、政策倾斜,新晋热门高薪不内卷!0基础一站式就业完整路径,抢占先发优势!
上一小节中,我们介绍了构造函数和析构函数。这一小节,我们来介绍一个特殊的构造函数。
先来看一个例程:
int main(int argc,char **argv) { Staff staffA; Staff staffB = staffA; return 0; }
我们先实例化了一个对象 staffA,然后又实例化了一个对象 staffB。希望 staffB 和 staffA 具有相同的内容,或者说希望 staffB 是 staffA 的副本,那么我们一般直接在实例化的时候进行赋值就可以了。
Staff staffB = staffA;
这样做了之后,C++ 会自动为我们拷贝 staffA 中的成员变量到 staffB 的成员变量中,但是这种自动拷贝机制在某些情况下无法完成我们想要的动作,甚至有可能会出错。我们来具体看一下。
在 Staff 类中添加一些内容:
Staff.hpp
#include <string> class Staff { public: Staff(std::string _name, int _age); ~Staff(); public: std::string name; int age; char * mem = nullptr; };
Staff.cpp
#include "Staff.hpp" #include <stdio.h> Staff::Staff(std::string _name, int _age) { mem = (char *)malloc(20); name = _name; age = _age; printf("构造函数被调用\n"); } Staff::~Staff() { if(mem != nullptr){ free(mem); mem = nullptr; } printf("析构函数被调用\n"); }
在上面的代码中,在类中定义了一个指针,在构造函数中,通过 malloc 函数分配了一个 20 字节大小的堆内存,然后将这片堆内存的首地址赋值给了这个指针。在析构函数中,我们将这片堆内存释放掉。
这个时候,我们再进行一开始的操作:
Staff staffB = staffA;
先来看看 staffA 在实例化之后的内存布局:
mem 指针指向了一片 20 个字节大小的堆内存。
这个时候,再来看看执行了Staff staffB = staffA;
之后,staffB 的内存布局会怎么样:
可以看到,在 C++ 默认的复制模式之下,两个对象中的 mem 指针指向了同一片内存。因为 C++ 默认的复制模式只会简单得把成员的值进行复制,面对这个 mem 指针,他只会把指针的值进行拷贝,最后的结果就是 mem 指针指向了同一片内存。
这种拷贝方式,被称之为浅拷贝。
Staff staffB = staffA;
当我们使用这种方式实例化对象的时候,并不会调用普通构造函数,而是会调用一个特殊的构造函数,被称之为赋值构造函数或者拷贝构造函数。如果我们没有写,那么就会按照浅拷贝的方式来进行复制。一个拷贝构造函数看起来就像下面这样:
Staff(const Staff & staff);
这个函数中只有一个参数 staff,表示要拷贝的对象,在我们的例子中,就是 staffA。(const 和 & 我们在后续的课程中会具体讲解)
那么我们来完整的编写一下这个函数
Staff.hpp
#include <string> class Staff { public: Staff(std::string _name, int _age); Staff(const Staff & staff); ~Staff(); public: std::string name; int age; char * mem = nullptr; };
Staff.cpp
#include "Staff.hpp" #include <stdio.h> Staff::Staff(std::string _name, int _age) { mem = (char *)malloc(20); name = _name; age = _age; printf("构造函数被调用\n"); } Staff::Staff(const Staff & staff) { name = staff.name; age = staff.age; mem = (char *)malloc(20); memcpy(mem, staff.mem, 20); } Staff::~Staff() { if(mem != nullptr){ free(mem); mem = nullptr; } printf("析构函数被调用\n"); }
请验证,完成请求
由于请求次数过多,请先验证,完成再次请求
打开微信扫码自动绑定
绑定后可得到
使用 Ctrl+D 可将课程添加到书签
举报