类的复制控制

复制构造函数还以Sales_item类为例,
在声明与定义Sales_item()函数时,须重载此函数,Sales_item(const Sales_item&);
 最终表现为 Sales_item item1; Sales_item item2(item1); 假如重载了赋值构造函数,则可以对象直

接复制,形如 item1=item2;

在类内声明,重载
Sales_item(const Sales_item&);

类外定义:
Sales_item::Sales_item(const Sales_item& item)
{
    isbn==item.isbn;
    units_sold=item.units_sold;
    revenue=item.revenue;
   return *this;
}

这是类成员中没有指针成员的复制构造函数,假若存在指针型的成员,则另当别论。复制构造函数对于

一个类来说并不是必须的,假如真的有数据成员是指针型的,必须注意其复制形式,否则容易出错

 

类的成员数据假如含有指针类型的成员数据,能不定义复制构造函数就不定义,假如程序需要,等会再写这个。下边先写复制构造函数的详细细节:

复制构造函数可由编译器自动合成,假如显式定义了默认构造函数则不会调用默认合成的复制构造函数,

显式定义复制构造函数时,其形参类型是本类类型的引用,常用const修饰,且必须为本类的引用。

 

对象初始化形式:

string null_book=“999-99-9-999”; 这种方式,创建临时对象,在调用复制构造函数将临时对象复制给null_book;

string dots(10,'.');     直接初始化

string empty_copy=string(); 复制初始化

string empty_direct; 直接初始化

复制初始化时,都隐含了调用复制构造函数,这对某些类来说是很危险的。而且,这四个例子,中第一个和第三个调用operator=();

假若复制构造函数为私有的或者为explicit,则上述定义将是不允许的。

 返回值类型

经常返回类的引用,已传址的方式。

复制控制:

    有些类需要完全禁止复制,例如,iostream 类就不允许复制。想要禁止复制,可以只声明,但不定义。或者将复制构造函数设为私有的成员函数。

大多数类应定义复制构造函数和默认构造函数。如果定义了复制构造函数,也必须定义默认构造函数。。

Sales_item& Sales_item::operator=(const Sales_item& item)

{

    isbn=item.isbn;

    units_sold=item.units_sold;

    revenue=item.revenue;

    return *this;

}

复制构造函数与赋值常一起使用;当然Sales_item中没有指针类型,假若类中含有指针类型,则必须对指针类型进行复制控制!

类指针成员管理:

    设计具有指针成员的类时,类设计者首先需要决定的是该指针应提供声明行为。将一个指针复制到另一个指针时,两个指针指向同一个对象。这时两个指针指向同一个对象,当用一个指针修改该值甚至将该值删除时,而另一个指向此数据的指针却不知道,有可能出现垂悬指针,造成内存泄露。。,采用不同的复制控制策略,可以为指针成员实现不同的行为。

    1、指针成员采取常规指针型行为,这样的类具有指针的所有缺陷但无需特殊的复制控制。

    2、类可以实现所谓的“智能指针”行为,指针多指向的对象是共享的,但类能够防止悬垂指针。

    3、类采取值型行为,分别实现管理指针成员的三种不同方法。

   1的方法是有点不复责任的类。。。。。。。

   2的方法是将指针智能化,却对有些类来说不是必要的。。。。。。。。

   3的方法比较简单易懂,能解决一些结构不是很复杂类的指针成员管理。。。。。。。。

class HasPtr

{

    public:

          HasPtr(int *p,int i):ptr(p),val(i)

       {  }

//此处省略N个字

    private:

        int *ptr;

       int val;

};

在指针复制中,假若采用第三种方法,则必须为指针变量开辟新的地址空间,

HasPtr::HasPtr(const HasPtr& temp)

{

    ptr=new int (*temp.ptr);//此处完全开辟新的空间,不仅仅复制指针,同时也复制指针指向的数据。

    val=temp.val;

};

智能指针
   1.使用引用计数,每复制一次指针成员,智能指针类讲一个计数器与类指向的对象关联。使用计数跟踪该类有多少个对象共享同一指针。使用计数为零时删除对象。
   每次创建类的新对象时,初始化指针并将使用计数致一。当对象作为另一对象的副本而创建时,复制构造函数复制指针并增加与之相应的使用计数的值。对一个对象进行赋值时,赋值操作符减少左操作数所指对象的使用计数的值,并增加右操作数多指对象的使用计数的值。最后,调用析构函数时,析构函数减少使用计数的值,如果计数减致0,则删除基础对象。唯一的创新,决定于使用计数放在哪里。计数器不能直接放在HasPtr对象中。
    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 &orig):ptr(orig.ptr),val(orig.val){ ++ptr->use; }
     HasPtr& operator=(const HasPtr);
     ~HasPtr(){if(--ptr->use==0) delete ptr;}
    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;
}
以上是一种智能指针使用的例子

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zanglengyu

敲碗要饭

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值