前言:拷贝构造函数是C++中的重点之一,在这里对其知识进行一个简单的总结。
一、什么是拷贝构造函数
在C++中,对于内置类型的变量来说,在其创建的过程中用同类型的另一个变量来初始化它是完全可以的,如:
1 int value=100; 2 int new_value=value;//在变量new_value创建的同时用同类型的变量value来初始化它
那么对于自定义的数据类型来说,是否可以在该类的一个对象创建时用该类的另一个对象对其进行初始化呢?看下例:
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 Student()=default;//默认构造函数 7 Student(string name,int age):Name(name),Age(age){} //构造函数 8 ~Student(){}//析构函数 9 void message();//打印对象的信息 10 private: 11 string Name; 12 int Age; 13 }; 14 15 void Student::message(){ 16 cout<<"My name is "<<Name<<endl; 17 cout<<"I am "<<Age<<" years old"<<endl; 18 } 19 int main(){ 20 Student stu1("Tomwenxing",23); 21 Student stu2(stu1); 22 stu2.message(); 23 return 0; 24 }
由上面的例子可以看出可以用一个类的对象去对该类的另一个正在创建的新对象进行初始化。而完成这个工作的就是类中的拷贝构造函数。所谓拷贝构造函数是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化。如果编程者在编写自定义的类时没有自定义拷贝构造函数,那么编译器会在类中定义一个默认的拷贝构造函数。
语法:类名(const 类名 &对象名) { /*拷贝构造函数体*/}
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 Student()=default;//默认构造函数 7 Student(string name,int age):Name(name),Age(age){} //构造函数 8 Student(const Student& stu){ //拷贝构造函数 9 Name=stu.Name; 10 Age=stu.Age; 11 cout<<"调用了拷贝构造函数!"<<endl; 12 } 13 ~Student(){}//析构函数 14 void message();//打印对象的信息 15 private: 16 string Name; 17 int Age; 18 }; 19 20 void Student::message(){ 21 cout<<"My name is "<<Name<<endl; 22 cout<<"I am "<<Age<<" years old"<<endl; 23 } 24 int main(){ 25 Student stu1("Tomwenxing",23); 26 Student stu2(stu1); 27 stu2.message(); 28 return 0; 29 }
特别注意:
拷贝构造函数的函数名必须和类名相同,且其唯一的参数(对象的引用)是不可变的(const类型)
二、拷贝构造函数的调用
在C++中,有三种情况会使对象在创建时调用拷贝构造函数
case 1:对象以值传递的方式传入函数参数
当对象直接作为参数以值传递的方式传递给函数时,函数将调用类中的拷贝构造函数并将实参对象传递给该拷贝构造函数从而在内存中创建形参对象,该形参对象将在函数执行完毕后调用类的析构函数将其析构
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 Student(){//默认构造函数 7 cout<<"调用了默认构造函数 "<<this<<endl; 8 } 9 Student(string name,int age):Name(name),Age(age){//构造函数1 10 cout<<"调用了构造函数1 "<<this<<endl; 11 } 12 Student(const Student& stu){ 13 Name=stu.Name; 14 Age=stu.Age; 15 cout<<"调用了拷贝构造函数!"<<this<<endl; 16 } 17 ~Student(){//析构函数 18 cout<<"调用了析构函数 "<<this<<endl; 19 } 20 void message();//打印对象的信息 21 private: 22 string Name; 23 int Age; 24 }; 25 26 void Student::message(){ 27 cout<<"My name is "<<Name<<endl; 28 cout<<"I am "<<Age<<" years old"<<endl; 29 } 30 31 void func1(Student s){ 32 cout<<"调用了函数func1"<<endl; 33 cout<<"形参变量的地址为"<<&s<<endl; 34 } 35 int main(){ 36 Student stu("Tomwenxing",23); 37 cout<<"实参变量的地址为"<<&stu<<endl; 38 cout<<"准备调用函数func1"<<endl; 39 func1(stu); 40 cout<<"函数func1调研完毕"<<endl; 41 return 0; 42 }
case 2:对象以值传递的方式从函数返回
当对象以值传递的方式从函数返回时,函数会调用类中的拷贝构造函数并将要返回的对象传递给该拷贝构造函数从而在内存中创建一个临时对象,该临时对象会在返回后(不管有没有对象接收(拷贝)该临时对象)立马调用类中的析构函数进行析构。
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student { 5 public: 6 Student() {//默认构造函数 7 cout << "调用了默认构造函数 " << this << endl; 8 } 9 Student(string name, int age) :Name(name), Age(age) {//构造函数1 10 cout << "调用了构造函数1 " << this << endl; 11 } 12 Student(const Student& stu) { 13 Name = stu.Name; 14 Age = stu.Age; 15 cout << "调用了拷贝构造函数!" << this << endl; 16 } 17 ~Student() {//析构函数 18 cout << "调用了析构函数 " << this << endl; 19 } 20 void message();//打印对象的信息 21 private: 22 string Name; 23 int Age; 24 }; 25 26 void Student::message() { 27 cout << "My name is " << Name << endl; 28 cout << "I am " << Age << " years old" << endl; 29 } 30 31 Student func1() { 32 cout << "调用了函数func1" << endl; 33 Student s("Tomwenxing", 23); 34 cout << "函数中的局部对象s在内存中的地址:" << &s << endl; 35 return s;
36 } 37 int main() { 38 cout << "准备调用函数func1" << endl; 39 func1(); 40 cout << "函数func1调研完毕" << endl; 41 return 0; 42 }
case 3:对象在创建过程中被相同类型的其他对象初始化
当对象在创建过程中被同类型的其他对象进行初始化时,该对象会调用类中的拷贝构造函数并将对其初始化的对象作为实参传递给该类的拷贝构造函数,从而最终将本对象成功创建
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 Student(){//默认构造函数 7 cout<<"调用了默认构造函数 "<<this<<endl; 8 } 9 Student(string name,int age):Name(name),Age(age){//构造函数1 10 cout<<"调用了构造函数1 "<<this<<endl; 11 } 12 Student(const Student& stu){ 13 Name=stu.Name; 14 Age=stu.Age; 15 cout<<"调用了拷贝构造函数!"<<this<<endl; 16 } 17 ~Student(){//析构函数 18 cout<<"调用了析构函数 "<<this<<endl; 19 } 20 void message();//打印对象的信息 21 private: 22 string Name; 23 int Age; 24 }; 25 26 void Student::message(){ 27 cout<<"My name is "<<Name<<endl; 28 cout<<"I am "<<Age<<" years old"<<endl; 29 } 30 31 int main(){ 32 Student stu1("Tomwenxing",23); 33 Student stu2(stu1);//初始化形式一 34 Student stu3=stu1;//初始化形式二 35 return 0; 36 }