- 含有对象成员的构造函数
- 深复制与浅复制
- 拷贝(复制)构造函数
第一部分:含有对象成员的构造函数
以下是一个学生 类包含日期成员出生日期的代码
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year,int month,int day):year(year),month(month),day(day)
{
cout << "Date 构造函数被调用" << endl;
}
void printDate()
{
cout << year << "年" << month << "月" << day << "日";
}
private:
int year,month,day;
};
class Student
{
public:
Student(string name,Date birthday) : name(name),birthday(birthday)
{
cout << "student 的构造函数被调用" << endl;
}
Student(string name,int year,int month,int day):name(name),birthday(year,month,day)
{
cout << "Student 的构造函数被调用222" << endl;
}
void printStudentInfo()
{
cout << "姓名" << name << ",出生日期" << endl;
birthday.printDate();
cout << endl;
}
private:
string name;
Date birthday;
};
int main()
{
Student stu1("小明",{2002,5,4}),stu2("小红",2003,3,6);
stu1.printStudentInfo();
stu2.printStudentInfo();
return 0;
}
Date 构造函数被调用
student 的构造函数被调用
Date 构造函数被调用
Student 的构造函数被调用222
姓名小明,出生日期
2002年5月4日
姓名小红,出生日期
2003年3月6日
小结:含有对象成员的类创建对象时,对象成员的初始化要在初始化列表中,运行时会先调用对象成员的构造函数,再调用当前类自己的构造函数。
第2部分:深复制与浅复制
#include<iostream>
using namespace std;
class Mystring
{
public:
Mystring(const char* str)
{
length = strlen(str);
data = new char[length + 1];
strcpy(data,str);
}
~Mystring()
{
delete[] data;
}
void printString()
{
cout << data << endl;
}
private:
char* data;
int length;
};
int main()
{
Mystring s("Hello world!");
s.printString();
Mystring s2 = s;
s2.printString();
return 0;
}
浅复制:浅复制是默认的构造函数
Mystring s2 = s;
没有写拷贝构造函数时,系统会自动生成一个“默认拷贝构造函数”,它会对每个成员变量做“逐成员复制”。
对于普通变量(如 int length)是没问题的,但对于指针(char* data),浅复制只是把地址复制过去,不会新建一份数据内容。
结果就是 s.data 和 s2.data 都指向同一块内存!
这就会导致:
两个对象共享同一块堆内存
当 s 和 s2 析构时,都执行 delete[] data,会对同一内存释放两次,造成程序崩溃或未定义行为(⚠️ 危险)
那么深复制的时候:就是复制内容,而不是复制指针地址,所以你只需要手动实现拷贝构造函数。
Mystring(const Mystring& other)
{
length = other.length;
data = new char[length + 1]; // 分配新内存
strcpy(data, other.data); // 复制内容
}
所以这个就是以下的区别:
第三部分:拷贝(复制)构造函数
#include<iostream>
using namespace std;
class Mystring
{
public:
Mystring(const char* str)
{
length = strlen(str);
data = new char[length+1];
strcpy(data,str);
cout << "Mystring的构造函数被调用" << endl;
}
Mystring(const Mystring& str)
{
length = str.length;
data = new char[length+1];
strcpy(data,str.data);
cout << "Mystring 的拷贝构造函数被调用" << endl;
}
~Mystring()
{
delete[] data;
}
void printString()
{
cout << data << endl;
}
private:
char* data;
int length;
};
int main()
{
Mystring s("Hello world");
s.printString();
Mystring s2(s);
s2.printString();
return 0;
}
- 必须使用引用参数(避免无限递归调用)
- 通常为 const 引用(保证源对象不被修改)
- 编译器默认生成(仅当类无用户自定义构造函数时)
那这里面的拷贝构造函数是什么?
Mystring(const Mystring& str)
{
length = str.length;
data = new char[length + 1]; // 分配新空间
strcpy(data, str.data); // 拷贝字符串内容
cout << "Mystring 的拷贝构造函数被调用" << endl;
}
用一个已经存在的对象去创建一个新的对象,并且为其分配新的内存( 深拷贝),防止多个对象共享同一块内存。
Mystring s2(s);
调用拷贝构造函数 Mystring(const Mystring& str) 创建新对象 s2
#include<iostream>
#include<string>
using namespace std;
class CPU{
public:
CPU(const string& cpu) : model(cpu){
cout << "cpu constructed" << endl;
}
void printInfo() const
{
cout << "CPU型号" << model << endl;
}
private:
string model;
};
class Monitor{
public:
Monitor(const string& monitor) : brand(monitor){
cout << "Monitor constructed" << endl;
}
void printInfo() const
{
cout << "Monitor品牌" << brand << endl;
}
private:
string brand;
};
class Computer{
public:
Computer(int memory,const string& cpuModel,const string& monitorBrand)
: memory(memory),cpu(cpuModel),monitor(monitorBrand){
cout << "Computer构造函数被调用" << endl;
}
void printInfo() const
{
cout << "内存容量 " << memory << " GB" << endl;
cpu.printInfo();
monitor.printInfo();
}
private:
int memory;
CPU cpu;
Monitor monitor;
};
int main()
{
Computer c(16,"Intel 890000","mac");
c.printInfo();
return 0;
}
- 定义一个Person类,包含char*类型的name,int age和Adress类型的address。Address是表示地址的类,包含char* street和int类型的houseNumber。请合理实现这两个类,使其能正常的完成如下的使用:
#include <iostream> #include <cstring> using namespace std; class Address { public: Address(const char* streetName, int houseNum) { street = new char[strlen(streetName) + 1]; strcpy(street, streetName); houseNumber = houseNum; cout << "Address构造函数被调用" << endl; } Address(const Address& other) { street = new char[strlen(other.street) + 1]; strcpy(street, other.street); houseNumber = other.houseNumber; } ~Address() { delete[] street; } void printAddress() const { cout << "地址: " << street << ", 门牌号: " << houseNumber << endl; } private: char* street; int houseNumber; }; class Person { public: Person(const char* n, int a, const Address& addr) : age(a), address(addr) { name = new char[strlen(n) + 1]; strcpy(name, n); cout << "Person构造函数被调用" << endl; } Person(const Person& other) : age(other.age), address(other.address) { name = new char[strlen(other.name) + 1]; strcpy(name, other.name); } ~Person() { delete[] name; } void printInfo() const { cout << "姓名: " << name << ", 年龄: " << age << endl; address.printAddress(); } private: char* name; int age; Address address; }; int main() { Address addr("人民路", 100); Person p("张三", 20, addr); p.printInfo(); return 0; }