面向对象进阶--拷贝构造函数

在了解前可以先看下《C++有关拷贝构造函数(默认/浅/深拷贝构造函数)》

拷贝构造函数

1.初始化(调用构造函数初始化)

 

2.在使用的s1(s2)(s1,s2都是对象),这种方式都是用拷贝构造函数初始化。

 

3.拷贝构造函数用student(const student &stu),这种当前类的引用,而不是当前类的对象,原因是当使用当前类的对象,本

身传递给形参就要用拷贝构造函数,然后拷贝构造函数中使用的又是类的对象,就会继续调用拷贝构造函数,这样会形成一

个死循环。同时,这也是C++语法要求。

使用const的原因是:加了const之后,可以将const对象和非const对象传递给形参stu,特别是如果没有const,那么const对象

就不能传入进去,因为const类型不能转换为非const类型。

Student::Student(Student &stu);
... ...
const Student stu1("小明", 16, 90.5);
Student stu2 = stu1;
Student stu3(stu1);

上面形式的代码会报错。

 

拷贝构造函数的调用时机

1.初始化对象,是在为对象开辟空间之后,第一次向空间中填充数据(调用构造函数)----只要创建对象就会调用构造函数。

初始化对于一个变量来说只有一次,但赋值可以有多次。初始化会调用构造函数,而赋值会调用重载过程。

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class stu{
 6     private:
 7         string m_name;
 8         int m_age;
 9         float m_score;
10     public:
11         stu(string name = "", int age = 0, float score = 0.0f);
12         stu(const stu &cp);
13     public:
14         void show();
15 //        stu func();
16         stu & operator=(const stu &cp);
17 };
18 
19 stu::stu(string name, int age, float score):m_name(name), m_age(age), m_score(score){
20 cout << "构造" << endl;}
21 
22 stu::stu(const stu &cp){
23     this -> m_name = cp.m_name;
24     this -> m_age = cp.m_age;
25     this -> m_score = cp.m_score;
26     cout << "拷贝" << endl; 
27 } 
28 
29 void stu::show(){
30     cout << m_name << " " << m_age << " " << m_score << endl;
31 }
32 
33 stu &stu::operator=(const stu &cp){
34     this -> m_name = cp.m_name;
35     this -> m_age = cp.m_age;
36     this -> m_score = cp.m_score;
37     cout << "重载" << endl; 
38 }
39 
40 int main()
41 {
42     stu s1("刘然", 18, 198.8);
43     stu s2("马平", 19, 169.7);
44     stu s3("马乐", 20, 178.9);
45     
46     stu s4 = s1;
47     s4 = s2;
48     s4 = s3;
49     
50     return 0;
51 }

 

 

2.以拷贝方式进行初始化对象:

实参使用普通构造函数初始化。

1)将其它对象作为实参

1 Student stu1("小明", 16, 90.5);  //普通初始化
2 Student stu2(stu1);  //以拷贝的方式初始化

 

2)在创建对象时同时赋值

1 Student stu1("小明", 16, 90.5);  //普通初始化
2 Student stu2 = stu1;  //以拷贝的方式初始化

 

3)函数的形参为类类型

1 void func(Student s){
2     //TODO:
3 }
4 
5 Student stu("小明", 16, 90.5);  //普通初始化
6 func(stu);  //以拷贝的方式初始化

 

4)函数返回值值为类类型

当函数的返回值为一个类类型,为了防止局部对象被销毁或者是通过返回值被修改,编译器会为这个对象创建一个临时对象(匿名),然后

将这个临时对象返回。在创建临时对象时就会使用拷贝构造函数。

1 Student func(){
2     Student s("小明", 16, 90.5);
3     return s;
4 }
5 
6 Student stu = func();

上面代码,在老一点的编译器上会看到两次拷贝,在G++和Dev C++中都是显示的构造。

 

 深拷贝和浅拷贝

1.浅拷贝和memcpy很类似,将数据按照二进制位复制。

 

2.将对象所持有的其他资源一并拷贝的行为叫做深拷贝。

 

重载赋值运算符

1.即使我们没有显式的重载赋值运算符,编译器也会以默认地方式重载它。默认重载的赋值运算符功能很简单,就是将原有对象的所有成员

变量一一赋值给新对象,这和默认拷贝构造函数的功能类似。

详细:点击

 

拷贝控制操作(三/五法则)

1.拷贝构造函数定义了当用同类型的另一个对象初始化新对象时做什么,赋值运算符定义了将一个对象赋予同类型的另一个对象时做什么,

析构函数定义了此类型的对象销毁时做什么。我们将这些操作称为拷贝控制操作。

由于拷贝控制操作是由三个特殊的成员函数来完成的,所以我们称此为“C++三法则”。在较新的 C++11 标准中,为了支持移动语义,又增加

了移动构造函数和移动赋值运算符,这样共有五个特殊的成员函数,所以又称为“C++五法则”。也就是说,“三法则”是针对较旧的 C++89 标

准说的,“五法则”是针对较新的 C++11 标准说的。为了统一称呼,后来人们干把它叫做“C++ 三/五法则”。

2.需要析构函数的类也需要拷贝和赋值操作

需要拷贝操作的类也需要复制操作(原因:点击

 

posted @ 2018-04-30 18:06  Hk_Mayfly  阅读(401)  评论(0编辑  收藏  举报