C++第六節:拷貝構造函數

拷貝構造函數

拷貝構造函數:通過拷貝一個已有對象來創建一個新的對象

1、聲明一個對象,並用另一個已經存在的對象初始化:

     1.1把已經存在的對象作爲新聲明對象的構造函數的參數

     1.2聲明一個對象,並用賦值表達式,用一個已有對象來初始化它

     1.3用new運算符,在堆上創建對象,並用一個已有對象對其進行初始化時

2、傳值的方式,從函數返回一個對象:

     2.1向函數傳參時,傳值調用時,形參是實參的拷貝

     2.2從函數傳值返回對象時,創建一個臨時對象,接受返回值,會調用拷貝構造函數

三大件:拷貝構造函數、析構函數、賦值運算符的重載

Vector.h

#ifndef __C__No731Class__Vector__
#define __C__No731Class__Vector__

#include <iostream>
using namespace std;
class Vector
{
public:
    int * rep;
    int size;
    
    Vector (int s = 0);
    Vector (int *r, int s);
    Vector (const Vector & v);  //拷貝構造函數
    ~Vector();
    const Vector & operator = (const Vector & v);  //重載賦值運算符
    void print();
};
#endif /* defined(__C__No731Class__Vector__) */
Vector.cpp

#include "Vector.h"
Vector::Vector (int s) : size(s)
{
    if (size <= 0)
        rep = NULL;
    else
    {
        rep = new int[size];
        for (int count = 0; count < size; ++count)
            rep[count] = 0;
    }
    cout << "默認構造函數" << endl;
}
Vector::Vector (int *r, int s)
{
    size = s;
    rep = new int[s];
    for (int count = 0; count < size; ++count)
        rep[count] = r[count];
    cout << "非默認構造函數" << endl;
}
Vector::Vector (const Vector &v)
{
    size = v.size;
    rep = new int[size];
    for (int count = 0; count < size; ++count)
        rep[count] = v.rep[count];
    cout << "重載構造函數" << endl;
}
Vector::~Vector()
{
    if(rep)
    {
        delete [] rep;
        rep = NULL;
    }
    cout << "析構Vector" << endl;
}
const Vector & Vector::operator = (const Vector & v)
{
    if (this != &v)
    {
        delete [] rep;
        rep = new int[v.size];
        for (int i = 0; i < v.size; ++i)
            rep[i] = v.rep[i];
        size = v.size;
    }
    cout << "重載=" << endl;
    return *this;
}
void Vector::print()
{
    cout << "size = " << size << endl;
    for (int i = 0; i < size; ++i)
        cout << rep[i] << " ";
    cout << endl;
}
main.cpp

#include <iostream>
#include "Vector.h"
int main(int argc, const char * argv[])
{
    Vector v1;
    v1.print();
    
    int array[5] = {1, 2, 3, 4, 5};
    Vector v2 (array, 5);
    v2.print();
    
    Vector v3(v2);
    v3.print();
    Vector v5 = v2;
    v5.print();
    
    Vector v4;
    v4 = v3;
    v4.print();
    
    return 0;
}
運行結果:

默認構造函數

size = 0


非默認構造函數

size = 5

1 2 3 4 5 

重載構造函數

size = 5

1 2 3 4 5 

重載構造函數

size = 5

1 2 3 4 5 

默認構造函數

重載=

size = 5

1 2 3 4 5 

析構Vector

析構Vector

析構Vector

析構Vector

析構Vector

臨時對象的系統開銷很大,傳值(包括參數、返回值)分別需要形參和返回值的臨時對象調用拷貝構造函數和析構函數,傳引用就顯得效率,傳參不需拷貝構造函數,返回時也不需要臨時變量和析構。

B、測試何時調用拷貝構造函數

Demo.h

#ifndef __C__No731Class__Demo__
#define __C__No731Class__Demo__

#include <iostream>
using namespace std;
class Demo
{
private:
    int i;
public:
    Demo (int n = 0);
    Demo (const Demo & a);
    ~Demo();
    const Demo & operator = (const Demo & a);
};
#endif /* defined(__C__No731Class__Demo__) */
Demo.cpp

#include "Demo.h"
Demo::Demo (int n)
{
    i = n;
    cout << "默認構造函數" << endl;
}
Demo::Demo (const Demo & a)
{
    i = a.i;
    cout << "拷貝構造函數" << endl;
}
Demo::~Demo()
{
    cout << "析構Demo" << endl;
}
const Demo & Demo::operator = (const Demo & a)
{
    i = a.i;
    cout << "重載=" << endl;
    return * this;
}
main.cpp

#include "Demo.h"
Demo foo(Demo x)   //a傳給x,拷貝構造函數
{
    Demo d;        //默認構造函數
    return d;      //開闢一個臨時的形參空間Nu接收d,d傳給Nu,拷貝構造函數(優化省略)
}
int main()
{
    Demo a (2);    //默認構造函數
    {
        Demo b;    //默認構造函數
        b = foo(a);//重載=,析構d,析構x
    }//析構b
    Demo c = a;    //拷貝構造函數
    return  0;     //析構c,析構a
}
運行結果:

默認構造函數

默認構造函數

拷貝構造函數

默認構造函數

重載=

析構Demo

析構Demo

析構Demo

拷貝構造函數

析構Demo

析構Demo


發佈了31 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章