【C++】Copy Constructor

来源:互联网 发布:wtf全知之眼bgm 编辑:程序博客网 时间:2024/04/28 01:31

原链接:http://www.waitingfy.com/archives/1033

Copy Constructor 是一个特殊的构造函数,一般只有一个参数,这个参数一般是用const修饰的,对自己类的一个引用(reference)。什么时候会用到Copy Constructor?

当我们定义一个对象时,它是由另外一个对象来初始化的时候就用到Copy Constructor了。还有就是在一个方法以值作为参数传进去或者一个方法中以值作为返回。

对于我这新手C++,Copy Constructor 用的比较少,真正用到了也不知道,因为一个类缺少 Copy Constructor 时,编译器会自动生成一个。


系统默认会提供一个Copy Constructor

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
classPeople{
private:
    intm_age;
public:
    People(intage):m_age(age){
        cout << "constructor"<< endl;
    }
 
    ~People(){
        cout << "destructor"<< endl;
    }
    intgetAge()const{
        returnm_age;
    }
};

一个简单的类,叫People,只有一个属性age

?
1
2
3
4
People p1(18);
    cout << "p1's age " << p1.getAge() << endl;
    People p2(p1);
    cout << "p2's age " << p2.getAge() << endl;

代码工作非常符合我们预期,因为系统会提供一个Copy Constructor,对类里的属性进行简单的赋值工作



2.2自定义的Copy Constructor

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
classPeople{
private:
    intm_age;
public:
    People(intage):m_age(age){
        cout << "constructor"<< endl;
    }
    //copy constructor
    People(constPeople& p){
        cout << "copy constructor" << endl;
    }
 
    ~People(){
        cout << "destructor"<< endl;
    }
    intgetAge()const{
        returnm_age;
    }
};
People p1(18);
    cout << "p1's age " << p1.getAge() << endl;
    People p2(p1);
    cout << "p2's age " << p2.getAge() << endl;

2.3还有两种情况会触发调用Copy constructor

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
//作为一个值从函数中返回
People getPeople(){
    People p1(20);
    returnp1;//会调用 copy constructor
}
//以值作为参数传入
voidsetPeople(People p1){//以值传入会调用 copy constructor
    //do nothing
}
 
voidsetPeople(People& p1){//以引用传入不会调用 copy constructor
    //do nothing
}

因为调用copy constructor的消耗比较大,所以一般都以引用方式作为函数参数。

 

3. copy constructor 与 assignment operator 的区别

我们忘记提到的是下面这种写法也会触发copy constructor:

?
1
2
3
4
People p1(18);
    cout << "p1's age " << p1.getAge() << endl;
    People p2 = p1;
    cout << "p2's age " << p2.getAge() << endl;

这种写法似乎跟赋值很像。

我们修改People的类,增加重载=操作符。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
classPeople{
private:
    intm_age;
public:
    People(intage):m_age(age){
        cout << "constructor"<< endl;
    }
 
    People(constPeople& p){
        cout << "copy constructor" << endl;
    }
 
    People& operator=(constPeople& p1){
        cout << "assignment operator" << endl;
        m_age = p1.getAge(); 
                return*this
    }
 
    ~People(){
        cout << "destructor"<< endl;
    }
    intgetAge()const{
        returnm_age;
    }
};
//测试代码
People p1(18);
    cout << "p1's age " << p1.getAge() << endl;
    People p2 = p1;
    cout << "p2's age " << p2.getAge() << endl;
    p2 = p1;

通过上面的输出结果我们发现:

= 什么时候会调用Copy Constructor呢?在初始化的时候,也就是第一个 People p2 = p1。因为Copy Constructor 是一种 Constructor,也是负责初始化的。

什么时候=是赋值呢?两个都已经初始化,再调用=就是赋值了。

 

4. 浅拷贝和深拷贝

 

我们上面的类People只有一个简单的属性age,还是int类型的,进行简单的赋值就是浅拷贝,但是People类将来会变的复杂起来,后面可能会增加指针类型的属性。那么就会涉及到深拷贝了。

 

我的理解就是:浅拷贝:两个变量进行浅拷贝时,它们指向同一个地址,它们的值相同。这样会有问题,当其中的一个析构了那个地址,另外一个也没有了,有时候会发生错误,但浅拷贝比较廉价。

深拷贝:两个变量进行深拷贝时,第二变量会重新申请一块区域来存放跟第一个变量指向地址的值。两个东西完全是独立的,只是值相同。消耗比较大,因为要重新申请空间。







0 0
原创粉丝点击