例1
深拷贝
#include<iostream>
class A
{
public:
A():_n(0),_p(NULL){}
explicit A(int n):_n(n),_p(new int[n]){}
A(int n,int *p):_n(n),_p(p){}
//这是拷贝构造 使用const关键字修饰表示不修改引用内容
A(const A & that);
//这是操作符重载,也叫赋值构造函数
//返回A类类型的一个引用,传入的是A类型的一个引用,不修改引用的内容,使用const
A & operator=(const A & that);
virtual ~A(){if(_p) delete[] _p,_p=NULL;}
public:
//下标操作符重载,表示返回一个int类型的引用,传入的参数时int类型的变量
int & operator[](int i);
//下标操作符的另一种形式
const int & operator[](int i)const;
void display()
{
for(int i=0;i<this->_n;i++)
std::cout<<this->_p[i]<<" ";
std::cout<<std::endl;
}
private:
int _n;
int *_p;
};
//构造函数的实现
A::A(const A & that)
{
//将传进来的that._n赋值给当前对象的_n数据对象
this->_n = that._n;
//然后动态开辟一片存储区域,大小为this->_n
//然后使用for循环将that._p[i]赋给this->_p[i]
this->_p = new int[this->_n];
for(int i=0;i<this->_n;i++)
this->_p[i] = that._p[i];
//构造函数没有返回值
}
//=重载函数的实现
A & A::operator=(const A & that)
{
this->_n = that._n;
//如果当前指针存在先进行销毁
if(_p)
delete[] _p;
_p = new int[_n];
for(int i=0;i<_n;i++)
_p[i] = that._p[i];
//最后返回一个引用
return *this;
}
//[]重载函数的实现
int & A::operator[](int i)
{
return _p[i];
}
const int & A::operator[](int i)const
{
return _p[i];
}
int main()
{
A a(4);
for(int i=0;i<4;i++)
a[i]=i+1;
std::cout<<"a.display"<<std::endl;
a.display();
A b = a;//使用赋值构造函数将a对象的数据对象赋值给b对象
std::cout<<"b.display"<<std::endl;
b.display();
A c(4);
for(int i=0;i<4;i++)
c[i]=i+1;
std::cout<<"c.display"<<std::endl;
c.display();
A d(c);//使用拷贝构造函数,将c的数据对象拷贝给d对象
std::cout<<"d.display"<<std::endl;
d.display();
return 0;
}
输出:
a.display
1 2 3 4
b.display
1 2 3 4
c.display
1 2 3 4
d.display
1 2 3 4
例2
使用右值操作实现移动赋值和移动赋值构造函数
#include <iostream>
class A{
public:
//构造函数
A():_n(0),_p(nullptr){}
//但参数构造函数
explicit A(int n):_n(n),_p(new int[n]){}
//双参数构造函数
A(int n,int *p):_n(n),_p(p){}
//——————————&&表示右值引用,在函数内部也是按照左值对待——————————//
A(A && that);//右值引用拷贝构造函数
A & operator=(A && that);//右值引用”=“重载构造函数,或者叫赋值构造函数
//——————————&&表示右值引用,在函数中也是按照左值对待——————————//
virtual ~A() {if(_p){delete [] _p,_p=nullptr;}}
public:
//"[]"重载
int & operator[](int i);
const int & operator[](int i)const;
void display()
{
for(int i=0;i<this->_n;i++)
std::cout<<this->_p[i]<<" ";
std::cout<<std::endl;
}
int* check()
{
return _p;
}
private:
int _n, *_p;
};
//右值引用拷贝构造函数的实现
A::A(A && that)
{
//nullptr:c++11预定义的空指针类型nullptr_t的常对象
//nullptr这个指针类型可隐式转换为任意指针类型和bool类型,但不能转换为整数类型,以取代NULL
//修改that._n的值和that._p的指向,变为空指针
_n = that._n,_p = that._p,that._n=0,that._p=nullptr;
//*this = that;//此代码不会调用下面重载的赋值操作符函数
//that在函数内部是左值,只能传递左值引用但是现在传递的是右值引用
//*this=static_cast<A&&>(that);等价于*this=std::move(that);
//但是可能会出错
}
//右值引用赋值构造函数的实现
A & A::operator=(A && that)
{
if(_p){delete[]_p;}
_n = that._n,_p = that._p;that._n=0;that._p=nullptr;
return *this;
}
int & A::operator[](int i)
{
return _p[i];
}
const int & A::operator[](int i)const
{
return _p[i];
}
int main()
{
A a(4);
for(int i=0;i<4;i++)
a[i]=i+1;
std::cout<<"a.display"<<std::endl;
a.display();
//使用右值操作的构造函数需要将a转换为右值引用
A b(static_cast<A &&>(a));//使用拷贝构造函数,将c的数据对象拷贝给d对象
std::cout<<"b.display"<<std::endl;
b.display();
A c(4);
for(int i=0;i<4;i++)
c[i]=i+1;
std::cout<<"c.display"<<std::endl;
c.display();
A d=static_cast<A &&>(c);//使用赋值构造函数,将c的数据对象赋值给d对象
std::cout<<"d.display"<<std::endl;
d.display();
//使用右值操作的赋值构造函数需要将a转换为右值引用
A e = static_cast<A &&>(a);
//不会输出,因为使用右值引用,前面的A b(static_cast<A &&>(a));已经将a的所有权移交到b,现在的a没有内容
e.display();
return 0;
}
输出:
a.display
1 2 3 4
b.display
1 2 3 4
c.display
1 2 3 4
d.display
1 2 3 4
e.display
例3
考虑深拷贝和右值引用的移动构造两种情况
#include<iostream>
using namespace std;
class A{
public:
A():_n(0),_p(nullptr){}
explicit A(int n):_n(n),_p(new int[n]){}
A(int n,int *p):_n(n),_p(p){}
//实现深拷贝的传递const,不需要修改引用数据对象的值
A(const A & that);// 1
//实现移动语义,需要传递右值,需要修改引用数据对象的值
A(A && that);
//实现深拷贝的赋值操作符重载,不需要修改引用数据对象的值
A & operator=(const A & that);// 2
//实现移动语义赋值操作符重载,需要修改引用数据对象的值
A & operator=(A && that);
virtual ~A(){if(_p){delete[] _p,_p=nullptr;}}
public:
int & operator[](int i);
const int & operator[](int i)const;
void display()
{
for(int i=0;i<this->_n;i++)
std::cout<<this->_p[i]<<" ";
std::cout<<std::endl;
}
private:
int _n,*_p;
};
//拷贝构造函数的实现
A::A(const A & that)
{
this->_n = that._n;
this->_p = new int[this->_n];
for(int i=0;i<this->_n;i++)
this->_p[i] = that._p[i];
}
//普通赋值构造函数的实现
A & A::operator=(const A & that)
{
this->_n = that._n;
//如果当前指针存在先进行销毁
if(_p)
delete[] _p;
_p = new int[_n];
for(int i=0;i<_n;i++)
_p[i] = that._p[i];
//最后返回引用
return *this;
}
//[]操作赋重载的实现
int & A::operator[](int i)
{
return _p[i];
}
const int & A::operator[](int i)const
{
return _p[i];
}
//右值引用拷贝构造函数实现
A::A(A && that)
{
_n = that._n,_p = that._p,that._n=0,that._p=nullptr;
}
//右值引用赋值构造函数实现
A & A::operator=(A && that)
{
if(_p){delete[]_p;}
_n = that._n,_p = that._p;that._n=0;that._p=nullptr;
return *this;
}
int main()
{
A a(4);
for(int i=0;i<4;i++)
a[i] = i+1;
A b(a);//1 调用拷贝构造函数
std::cout<<"b.display"<<std::endl;
b.display();
//这里还可以使用a进行赋值,因为b的拷贝是深拷贝,a的数据对象还存在
A c = a;//2 调用普通赋值版本
std::cout<<"c.display"<<std::endl;
c.display();
//static_cast<new_type>(expression)
A d(static_cast<A &&>(a));//调用移动构造版本
std::cout<<"d.display"<<std::endl;
d.display();
A e = static_cast<A && >(a);//调用移动赋值版本
std::cout<<"e.display";
//不会输出,因为使用右值引用,前面的A b(static_cast<A &&>(a));已经将a的所有权移交到b,现在的a没有内容
e.display();
}
输出:
b.display
1 2 3 4
c.display
1 2 3 4
d.display
1 2 3 4
e.display
例4
左值引用实现移动构造
#include<iostream>
using namespace std;
class A{
public:
A():_n(0),_p(nullptr){}
explicit A(int n):_n(n),_p(new int[n]){}
A(int n,int *p):_n(n),_p(p){}
//实现深拷贝的传递const,不需要修改引用数据对象的值
A(const A & that);// 1
//实现移动语义,拿掉const即可修改引用数据对象的值
A(A & that);
//实现深拷贝的赋值操作符重载,不需要修改引用数据对象的值
A & operator=(const A & that);// 2
//实现移动语义赋值操作符重载,需要修改引用数据对象的值,去掉const即可
A & operator=(A & that);
virtual ~A(){if(_p){delete[] _p,_p=nullptr;}}
public:
int & operator[](int i);
const int & operator[](int i)const;
void display()
{
for(int i=0;i<this->_n;i++)
std::cout<<this->_p[i]<<" ";
std::cout<<std::endl;
}
private:
int _n,*_p;
};
A::A(A & that)
{
_n = that._n,_p = that._p,that._n=0,that._p=nullptr;
}
A::A(const A & that)
{
this->_n = that._n;
_p = new int[_n];
for(int i=0;i<_n;i++)
_p[i] = that._p[i];
}
A & A::operator=(A & that)
{
_n = that._n,_p = that._p,that._n=0,that._p=nullptr;
return *this;
}
A & A::operator=(const A & that)
{
this->_n = that._n;
if(_p){delete[] _p;}
_p = new int[_n];
for(int i=0;i<_n;i++)
_p[i] = that._p[i];
return *this;
}
int main()
{
A a1;//缺省构造
const A a2;//缺省构造
A a3(a1);//调用A::A(A&),移动拷贝构造
A a4(a2);//调用A::A(const A &)深拷贝构造
//对于非常量必须转型为常量才能进行深拷贝,比如我要用非常量a1进行深拷贝
//const_cast可以取消或者设置const属性
//下面这个目的就是将a1转换成const A类型
//const_cast<new_type>(expression)
A a5(const_cast<const A & >(a1));
A a6,a7,a8;//缺省构造
a6 = a1;//调用A::A operator=(A&)
a7 = a2;//调用A::A operator=(const A&)
a8 = const_cast<const A &>(a1);//将a1转型为常量,然后赋值给a8调用A::Aoperator=(const A &)
return 0;
}