1. 拷贝构造函数
功能:使用一个已经存在的对象来初始化一个新的同一一类型的对象
声明:只有一个参数并且参数为该类对象的引用
如果类中没有说明拷贝构造函数,则系统自动生成一个缺省复制构造函数,作为该类的公有成员
2. 拷贝构造函数的调用情况
1) 用已有对象初始化对象会调用拷贝构造函数
2) 当函数的形参是类的对象,调用函数时,进行形参与实参结合时使用
3) 当函数的返回值是类对象,函数执行完成返回调用名时使用(返回值不是局部的类对象,当传递对象或返回对象时,一般用引用,由于引用不会调用构造函数,提高效率)
3. 深拷贝与浅拷贝
1) 浅拷贝——使用系统提供的默认构造函数完成的复制,源对象与复制对象共用一份指针,仅仅是引用的变量不同(对象名不同),对其中任何一个对象的改动都会影响另一个对象。
2) 深拷贝——不使用系统提供的默认构造函数,源头对象与复制对象相互独立,其中任何对象的改动都不会对另外一个对象造成影响
3) 赋值操作
void operator=(constString& t);//=运算符必须要实现深拷贝
4) 禁止拷贝
对于独一无二的对象禁止拷贝,将拷贝构造函数私有化
5) 拷贝构造函数与复制运算符重载函数的区别
两者都是从另一个对象中复制函数,但是两者在使用时有很大区别:
A. 是否产生新的对象
拷贝构造函数调用时必须产生一个对象,用一个已存在的对象去构造一个不存在的对象;
=赋值运算符是通过参数传进来,对已经存在的对象赋值,不产生新的对象,用一个已存在的对象去覆盖另一个已存在的对象。
B. 调用的时机不同
拷贝构造函数是用已经存在的对象初始化另一个新的对象,即在对象创建并初始化时调用的;
而=赋值运算符重载函数要在对象初始化完成后才会被调用。
C. 是否释放原来的内存空间(类的数据成员是指针)
拷贝构造函数需要重新申请内存空间,不能和传递的对象共用相同的内存空间,否则在析构函数会出现二次释放的问题;
=赋值运算符函数使用时,对象已经存在,即数据指针的内存空间已经存在,但这段内存空间的长度不一定满足赋值的需求,所以需要先释放已有的内存空间,再根据赋值对象的数据成员大小重新申请内存空间,然后再赋值
示例:
[main.cpp]
#include <iostream>
#include "String.h"
using namespace std;
int main()
{
String s;//默认构造函数
s ="hello1";//转换构造函数+赋值构造函数+析构函数
s.Display();
Strings1("hello2");//转换构造函数
s1.Display();
Strings2(s1);//拷贝构造函数
s2.Display();
Strings3("world!");//转换构造函数
s3 ="hello world";//转换构造函数+赋值构造函数+析构函数
s3.Display();
return 0;
}
[String.h]
#ifndef _STRING_H_
#define _STRING_H_
class String
{
public:
String();
~String();
void Display();
String(char*str);
String(constString& other);//拷贝构造函数
String&operator = (const String& other);//=赋值运算服
private:
char *str_;
};
#endif
[String.cpp]
#include <iostream>
#include <string.h>
#include "String.h"
using namespace std;
String::String()
{
str_ = newchar('\0');
cout <<"default constructor String" << endl;
}
String::~String()
{
cout <<"destroy String" << endl;
delete [] str_;
}
String::String(char *str)
{
cout <<"constructor String" << endl;
int len =strlen(str) + 1;
str_ = newchar[len];
memset(str_, 0,len);
strcpy(str_,str);
}
void String::Display()
{
cout <<str_ << endl;
}
String::String(const String& other)
{
//cout <<"copy" << endl;
int len =strlen(other.str_) + 1;
str_ = newchar[len];
memset(str_, 0,len);
strcpy(str_,other.str_);
}
String& String::operator = (const String& other)
{
//cout<< "=" << endl;
if(this ==&other)
{
return*this;
}
int len =strlen(other.str_) + 1;
delete [] str_;
str_ = newchar[len];
memset(str_, 0,len);
strcpy(str_,other.str_);
}
4. 空类默认生成的成员
class Empty
{
Empty();//默认构造函数
Empty(const Empty&);//默认拷贝构造函数
~Empty();//默认析构函数
Empty& operator=(const Empty&);//默认赋值运算符
Empty* operator&();//取地址运算符
const Empty* operator&() const;//取地址运算符const
};