类中的默认构造,拷贝构造,赋值构造,移动构造实例

类中的默认构造,拷贝构造,赋值构造,移动构造实例

1. 类的默认构造,拷贝构造,赋值构造

#include<iostream>
#include<vector>
#include<string.h>
#include<stdio.h>
using namespace std;
class A {
   public :
       //构造函数
	   A(const char* str=0)
	   {
	       if(str)
		   {
			   _CStr=new char[strlen(str)+1];
			   strcpy(_CStr,str);
		   }
		   else
		   {
			   _CStr=new char[1];
			   *_CStr='\0';
		   }
		   cstr++;
		   cout<<"constrcutor:"<<cstr<<endl;
	   }
	   
	   //拷贝构造
       A(const A& other)
	   {
		  _CStr=new char[str(other._CStr)+1];
		  strcpy(_CStr,other._CStr);
		  ++cpstr;
		  cout<<"copy constrcutor:"<<cpstr<<endl;
	   }
	   
	   //赋值拷贝
	   A& operator=(const A&other)
	   {
		  cAssgn++;
		  cout<<"assigment construct:"<<cAssgn<<endl;
	      if(&other==this)
		  {
		     return *this;
		  }
		  delete[] _CStr;
		  _CStr=new char[strlen(other._CStr)+1];
		  strcpy(_CStr,other._CStr);		
		  return *this;
	   }
	   
	   //移动构造
	   A (A&& other):noexcept _CStr(other._CStr)
	   {
		   ++mvstr;
		   cout<<"move constrcutor:"<<mvstr<<endl;
		   other._CStr=nullptr;
	   }
	   //赋值移动
	   A& operator=(A&& other) noexcept 
       {
		   mvAssgn++;
		   cout<<"move assigment:"<<mvAssgn<<endl;
		   if(&other==this)
		   {
			   return *this;
		   }
		   delete[] _CStr;
		   _CStr=other._CStr;
		   other._CStr=nullptr;   //不再指向之前的资源
		   return *this;
	   }	   
	   ~A()
	   {
		   dstr++;
		   cout<<"destructor:"<<dstr<<endl;
		   if(_CStr)
		   {
			   delete[] _CStr;
			   _CStr=nullptr;
		   }
	   }
   private :
      char* _CStr;
      
	  static int cstr;
	  static int dstr;
	  static int cAssgn;
	  static int cpstr;
	  static int mvstr;
	  static int mvAssgn;
};

如上类A中私有成员变量是一个指针,这时要注意了,智能变量涉及动态内存的分配与回收。
(1)构造函数
需要注意 成员变量:char* _CStr内存空间的分配,分为两种情况:
① str不为空时,分配内存大小为: strlen(str)+1
② str为空时,分配内存大小为: 1, 用于存储字符串结束符:‘\0’

A(const char* str=0)
{
   if(str)
   {
      _CStr=new char[strlen(str)+1];
      strcpy(_CStr,str);
   }
   else
   {
      _CStr=new char[1];
      *_CStr='\0';
   }
}

(2) 拷贝构造函数

A(const A& other)
{
   _CStr=new char[strlen(other._CStr)+1];
   strcpy(_CStr,other._CStr);
   
}

(3) 赋值构造
复制构造函数,需要注意判断当前传入的other是否是自己本身(this),如果没有判断
就直接delete[] _CStr; 后面再拷贝被删除的_CStr就出问题了,因为此时_CStr变为了野指针。
因此需要在复制拷贝时需要进行判断拷贝对象是否为自己本身。

A& operator=(A& other) const
{
   if(&other==this)
   {
      return *this;
   }
   delete[] _CStr;
   _CStr=new char[strlen(other._CStr)+1];
   strcpy(_CStr,other._CStr);
   return *this;
}

2. 移动拷贝与移动赋值拷贝

移动构造与拷贝构造的区别在于移动构造不用开辟新的空间,用现有对象指针指向传入对象的内存空间,然后让传入对象的指针指向nullPtr。
在移动赋值拷贝时首先判断当前对象是否自己本身,如果只是则直接返回*this,如果不是则需要先将_CStr清空,然后将_CStr指针指向传入对象的_CStr的内存空间,最后传入对象的成员变量的指针置空。

A(A&& other):_CStr(other._CStr)
{
   other._CStr=nullPtr;
}
A& operator=(A&& other)
{
   if(&other==this)       //判断当前指针是否本身
   {
      return *this;
   }
   delete[] _CStr;        //清除之前所指向的空间
   _CStr=other._CStr;     //指向新的对象_CStr
   other._CStr=nullPtr;   //防止原来的指针变为野指针,将原来的指针指向nullPtr
}

3. 拷贝构造与移动构造在vector应用中时间效率的区别

      int A::cstr=0;
	  int A::dstr=0;
	  int A::cAssgn=0;
	  int A::cpstr=0;
	  int A::mvstr=0;
	  int A::mvAssgn=0;

 int main()
 {
    long timeStart=clock();
    vector<A>  vec;
    vec.resize(1000); //分配1000个A的空间,调用1000次A的构造函数
    for(int i=0;i<1000;i++)
    {
        vec.push_back(A("hello Wolrd!"));
    }
    double timeDiff=(clock()-timeStart)/1000;
    cout<<"consume time:"<<timeDiff<<"ms"<<endl;
    return 0;
 }

(1)调用移动构造

for(int i=0;i<1000;i++)
{
vec.push_back(A("hello Wolrd!"));  //A是一个临时对象或者将消值
}

若上代码执行1000次for循环,vector容器中添加A的临时对象,A(“Hello,World”)调用了1000000次构造函数,vec.push_back(A(“Hello,World”)) 2000000次移动构造函数,执行程序所用的时间如下:109ms
在这里插入图片描述
(2)调用拷贝构造

for(int i=0;i<1000;i++)
{
  A a("Hello world")
  vec.push_back(a);  
    //参数传递copy构造,vector内部移动元素是移动构造
}

若上代码执行1000次for循环,vector容器中添加A的临时对象,A(“Hello,World”)调用了1000000次构造函数,vec.push_back(A(“Hello,World”)) 1000000次拷贝构造函数,vec内部执行了1000000移动构造, 执行程序所用的时间如下:143ms
在这里插入图片描述
由上可以看看出移动构造比拷贝构造跟节省空间和时间资源

关于vector的底层函数实现在下一个小节讲解

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值