博客总结十二——C++复制控制

1、复制构造函数:
1)
单个形参,形参为对本类类型对象的引用,通常为const;
复制初始化(=赋值):调用复制构造函数;首先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象;
直接初始化(圆括号赋值):直接调用与实参匹配的构造函数;
ifstream file1("filename");//ok

ifstream file2="filename";//error,IO流对象不能被复制,所以不能使用复制初始

若要复制一个IO流对象,需要使用非const引用;

explicit?查查资料;
2)
当形参为非引用类型时,将复制实参的值;
当返回值为非引用类型时,将返回return语句中的值的副本;
当形参或者返回值为类类型时,由复制构造函数进行复制;
3)
vector<string> svec(5);//使用表示容量的单个形参来初始化容器
编译器首先使用string默认构造函数创建一个临时值来初始化svec,然后使用复制构造函数将临时值复制到svec的每个元素;
4)
如果我们没有定义复制构造函数,编译器就会为我们合成一个,执行逐个成员初始化,若类中有数组成员,合成复制构造函数将复制数组;
必须定义复制构造函数:类中有一个数据成员是指针,或者有成员表示在构造函数中分配的其他资源;
5)private可以禁止复制;但是类的友元和成员仍可以进行复制,完全禁止复制,可以声明一个private复制构造函数而不对其定义;
2、赋值操作符
Sales_item &operator=(const Sales_item &rhs){...return *this;}
3、析构函数
1)何时调用析构函数:
Sales_item *p=new Sales_item;
Sales_item item(*p);
delete p;//析构函数调用
Sales_item *p=new Sales_item[10];
vector<Sales_item> vec(p,p+10);
delete [] p;//析构函数调用,逆序撤销,(size()-1)~0
2)合适编写显示析构函数:
三法则:如果类需要析构函数,则也需要赋值操作符和复制构造函数;
析构函数可以执行任意操作,该操作时类设计者希望在类对象的使用完毕之后执行的,包括释放资源等;
3)合成析构函数:
编译器总会自动合成一个析构函数;
合成析构函数按对象创建顺序逆序撤销每一个非static成员;
即使我们编写了自己的析构函数,合成析构函数仍然运行;
首先执行自己的析构函数,再执行合成析构函数来撤销类的成员;
4、管理指针成员:
1)一个带指针成员的简单类:
2)
class HasPtr{..int *ptr;int val;..};
int job = 0;
HasPtr ptr1(&job,42);
HasPtr ptr2(ptr1);
两个对象的指针混在了一起,都指向了同一个对象,就算是两个指针的值不一样,int是独立的;
当修改其中一个指针指向的对象时,另一个类的指针指向的对象也会被修改;
3)悬垂指针:
int *ip = new int(42);
HasPtr ptr(ip,10);
delete ip;
ptr.set_ptr_val(0);//error:ptr对象的ptr指针已经不再指向有效的对象了;
4)定义智能指针:智能指针负责删除共享对象。
采用使用计数
第一种:使用计数类:
class U_Ptr
{
friend class HasPtr;
int *ip;
size_t use;
U_Ptr(int *p):ip(p),use(1){}
~U_Ptr(){delete ip;}
};
class HasPtr
{
public:
HasPtr(int *p,int i):ptr(new U_Ptr(p),val(i)){}
HasPtr(const HasPtr *rhs):ptr(rhs.ptr),val(rhs.val){++ptr->use;}
~HasPtr(){if(--ptr->use==0) delete ptr;}
HasPtr &operator=(const HasPtr&);
private:
U_Ptr *ptr;
int val;
};
HasPtr &HasPtr::operator=(const HasPtr &rhs)
{
++rhs.ptr->use;
if(--ptr->use == 0)
delete ptr;
ptr = rhs.ptr;
val = rhs.val;
return *this;
}
第二种:定义值型类
复制值型对象时,会得到一个不同的新副本,对副本所作的改变不会反映在原有对象上,反之亦然。
HasPtr(const int &p,int i):ptr(new int(p)),val(i){}
HasPtr(const HasPtr &rhs):ptr(new int (*rhs.ptr)),val(rhs.val){}
赋值操作符则不需要分配新对象;
复制构造函数不再复制指针,而是分配一个新的int对象,并初始化该对象以保存与被复制对象相同的值。每个对象都保存属于自己的int值的不同副本。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值