拷貝構造函數
拷貝構造函數:通過拷貝一個已有對象來創建一個新的對象
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