拷贝构造函数:
调用拷贝构造函数的情形
在C++中,下面三种对象需要调用拷贝构造函数(有时也称“复制构造函数”):
1)一个对象作为函数参数,以值传递的方式传入函数体;
2)一个对象作为函数返回值,以值传递的方式从函数返回;
3)一个对象用于给另外一个对象进行初始化(常称为赋值初始化);
如果在前两种情况不使用拷贝构造函数的时候,就会导致一个指针指向已经被删除的内存空间。对于第三种情况来说,初始化和赋值的不同含义是拷贝构造函数调用的原因。事实上,拷贝构造函数是由普通构造函数和赋值操作符共同实现的。描述拷贝构造函数和赋值运算符的异同的参考资料有很多。
通常的原则是:①对于凡是包含动态分配成员或包含指针成员的类都应该提供拷贝构造函数;②在提供拷贝构造函数的同时,还应该考虑重载"="赋值操作符号。原因详见后文。
拷贝构造函数必须以引用的形式传递(参数为引用值)。其原因如下:当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动的被调用来生成函数中的对象。如果一个对象是被传入自己的拷贝构造函数,它的拷贝构造函数将会被调用来拷贝这个对象这样复制才可以传入它自己的拷贝构造函数,这会导致无限循环直至栈溢出(Stack Overflow)。除了当对象传入函数的时候被隐式调用以外,拷贝构造函数在对象被函数返回的时候也同样的被调用。
隐式地拷贝构造函数
如果在类中没有显式的声明一个拷贝构造函数,那么,编译器会自动生成一个来进行对象之间非static成员的位拷贝(Bitwise Copy)。这个隐含的拷贝构造函数简单的关联了所有的类成员。注意到这个隐式的拷贝构造函数和显式声明的拷贝构造函数的不同在于对成员的关联方式。显式声明的拷贝构造函数关联的只是被实例化的类成员的缺省构造函数,除非另外一个构造函数在类初始化或构造列表的时候被调用。
拷贝构造函数使程序更有效率,因为它不用再构造一个对象的时候改变构造函数的参数列表。设计拷贝构造函数是一个良好的风格,即使是编译系统会自动为你生成默认拷贝构造函数。事实上,默认拷贝构造函数可以应付许多情况。
拷贝构造函数的格式
拷贝构造函数的声明:
class类名
{
public:
类名(形参参数)//构造函数的声明/原型
类名(类名&对象名)//拷贝构造函数的声明/原型
...
};
拷贝构造函数的实现:
类名::类名(类名&对象名)//拷贝构造函数的实现/定义
{函数体}
实例应用:
1、 classA a(b);
2、 classA a=b;
3、 classA x; classA *p=new classA(x);
例如:
#include "stdafx.h"
#include<iostream>
using namespace std;
class Vector
{
public:
Vector(int s=0);
Vector(int*,int);
Vector(const Vector& v);
~Vector()
{
dispose();
}
int getsize() const
{
return size;
}
const Vector& operator=(const Vector& x);
int & operator[](int index)
{
return rep[index];
}
const int& operator[](int index)const
{
return rep[index];
}
private:
int* rep;
int size;
void clone(const Vector& a);
void dispose();
};
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;
}
}
}
Vector::Vector(int* a,int s):size(s),rep(newint[s])
{
for(int count=0;count<size;++count)
{
rep[count]=a[count];
}
}
void Vector::clone(const Vector& a)
{
/*delete []rep;
rep=NULL;*/
this->size=a.size;
rep=new int[size];
for (int count=0;count<size;++count)
{
rep[count]=a[count];
}
}
Vector::Vector(const Vector& v)
{
clone(v);
}
void Vector::dispose()
{
delete []rep;
}
const Vector& Vector::operator=(const Vector& x)
{
if(this!=&x)
{
delete[] rep;
this->size=x.size;
rep=new int[size];
for (int count=0;count<size;++count)
{
rep[count]=x[count];
}
}
return *this;
}
ostream& operator<<(ostream& out,const Vector& x)
{
int s=x.getsize();
for(int i=0;i<s;++i)
{
out<<x[i]<<endl;
}
out<<endl;
return out;
}
bool operator==(const Vector& a,const Vector& b)
{
bool yes=true;
if(a.getsize()!=b.getsize())
{
yes=false;
}
else
{
int s,index=0;
s=a.getsize();
while (index<s&&a[index]==b[index])
{
++index;
}
if (index<s)
{
yes=false;
}
}
return yes;
}
int _tmain(int argc, _TCHAR* argv[])
{
Vector vec1;
cout<<vec1;
int array[5]={1,2,3,4,5};
Vector vec2(array,5);
cout<<vec2;
Vector vec3(vec2);
cout<<vec3;
if(vec3==vec2)
{
cout<<"hhhhhh";
}
Vector vec4;
vec4=vec3;
cout<<vec4<<endl;
return 0;
}
字符串拷贝复制函数:
例如:
#include "stdafx.h"
#include<iostream>
#include<string>
using namespace std;
class String1
{
public:
String1(char *p);
~String1()
{
delete[] p1;
}
String1(const String1& p2);
String1& operator=(const String1& p3);
friend ostream& operator<<(ostream& out,const String1& x);
private:
char *p1;
};
String1::String1(char *p)
{
if (p==NULL)
{
return;
}
else
{
int length=strlen(p);
p1=(char*)malloc(length+1);
strcpy(p1,p);
}
}
String1::String1(const String1& p2)
{
int length=strlen(p2.p1);
p1=(char*)malloc(length+1);
strcpy(p1,p2.p1);
}
String1& String1:: operator=(const String1& p3)
{
if (this!=&p3)
{
delete []p1;
p1=NULL;
int length=strlen(p3.p1);
p1=(char*)malloc(length+1);
strcpy(p1,p3.p1);
}
return *this;
}
ostream& operator<<(ostream& out,const String1& x)
{
cout<<x.p1<<endl;
return out;
}
int _tmain(int argc, _TCHAR* argv[])
{
String1 a("liu");
cout<<a<<endl;
String1 b(a);
cout<<b<<endl;
return 0;
}
例如二:
#include "stdafx.h"
#include<iostream>
using namespace std;
class Demo
{
public:
Demo(int n=0):i(n)
{
cout<<"default"<<endl;
}
Demo(const Demo&a)
{
i=a.i;
cout<<"copy"<<endl;
}
~Demo()
{
cout<<"de"<<endl;
}
const Demo& operator=(const Demo& a)
{
this->i=a.i;
cout<<"=";
return *this;
}
int get_value()
{
return i;
}
private:
int i;
};
Demo ff(Demo x)
{
Demo d;
return d;
}
int _tmain(int argc, _TCHAR* argv[])
{
Demo a(2);
{
Demo b;
b=ff(a);
}
Demo c=a;
return 0;
}