类--复制构造函数、析构函数

1、如果没有显示定义复制构造函数或赋值操作符,编译器通常会为我们定义。

2、复制构造函数、赋值操作符、析构函数总称 复制控制。编译器自动实现这些操作,蛋类也可以定义自己的版本。

3、有一种特别常见的情况需要类定义自己的复制控制成员的:类具有指针成员。
复制构造函数
1、是一种特殊的构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用。

2、当形参或返回值为类类型时,有复制构造函数进行复制。

3、即使我们定义了其他构造函数,也会合成复制构造函数。,他的行为是,执行逐个成员初始化,将新对象初始化为原对象的副本。

4、为了防止复制,类必须显示声明其复制构造函数为private。
如果想要连友元和成员中的复制也禁止,就可以声明一个private复制构造函数但不对其定义。

5、声明而不定义成员函数式合法的,但是使用为定义成员的人和尝试将导致连接失败。

6、大多数类应定义复制构造函数和默认构造函数。

7、如果定义了复制构造函数,也必须定义默认构造函数。

复制构造函数以下部分来自百度百科:
何时使用复制构造函数:按值传递对象,函数返回对象,用一个对象初始化另一个对象(即复制初始化),根据元素初始化列表初始化数组元素,这四种情况都将调用复制构造函数。记住: 复制构造函数只能用于初始化,不能用于赋值,赋值时不会调用复制构造函数,而是使用赋值操作符。

复制初始化与复制构造函数:复制初始化使用=等于符号来初始化, 复制初始化也是创建一个新对象,并且其初值来自于另一个已存在的对象,复制初始化总是调用 复制构造函数来初始化的。复制初始化时,首先使用指定的 构造函数创建一个 临时对象,然后用 复制构造函数将临时对象的每个 非static成员依次的复制到新创建的对象,复制构造函数执行的是逐个成员初始化。注意, 这里是用一个已存在的对象创建另一个新对象,与用构造函数直接创建一个新对象不一样,使用构造函数初始化时不会使用另一个对象。比如有类hyong,则语句hyong m(1,2)调用构造函数 直接初始化,而语句hyong n=m则是用已存在的对象m去初始化一个新对象n,属于 复制初始化。 

理解赋值与复制初始化的区别(重点): 赋值是在两个已存在的对象间进行的,也就是用一个已存在的对象去改变另一个已存在对象的值。赋值将调用赋值操作符对对象进行操作,赋值操作符将在操作符重载中讲解。比如有类hyong,有语句hyong x(1);hyong y(1,2)则x=y;这就是赋值,因为对象x和y是已经存在的对象,而语句hyong x=y;则是复制初始化, 是用一个已存在的对象y去创建一个新对象x,所以是复制初始化。

复制初始化赋值是在两个对象之间进行的操作,而 直接初始化则不是

复制构造函数的形式:hyong(const hyong & obj);它接受一个 指向类对象的常量引用作为参数。定义为 const是必须的,因为复制构造函数只是复制对象,所以没必要改变传递来的对象的值,声明为引用可以节省时间,如果是按值传递的话就会生成对象的副本,会浪费资源,而引用就不会。

为什么需要定义自己的复制构造函数:如果类只包含类类型成员和内置类型的成员,则可以不用显示定义复制构造函数。但如果类中包含有指针或者有分配其他类型资源时,就 必须重新定义复制构造函数。因为类中有指针成员,当把用一个对象初始化另一个对象时,这时两个对象中的指针都指向同一段内存,这时如果其中一个对象被消毁了,这时对象中指针所指向的内存也同样被消毁,但另一个对象确不知道这种情况,这时就会出现问题。比如hyong类中含有一个成员指针p,当声明了hyong x=y其中y也是hyong类的对象,这时对象x和y中的指针成员p都指向同一段内存,而如果y被消毁,但x还没被消毁时就会出问题,这时y中对象的成员指针p已经释放了该内存资源,而x中的成员指针p还不知道已经释放了该资源,这时就会出问题。因为对象x和y中的成员指针共享同一段内存,所以对y中的成员指针p的修改就会影响到对象x中的成员指针。所有这些情况都需要重定义复制构造函数来显示的初始化成员的值,这种初始化方式也被称为 深度复制。  

复制构造函数的使用
  class hyong
  {
  public:
  hyong();
  hyong(int i);
  hyong(const hyong& obj);
  ~hyong();
  void h(hyong k);
  hyong f();
  int a,b,c;
  };
  hyong::hyong()
  {
  a=b=c=0;
  cout<<"构造函数"<<"\n";
  }
  hyong::hyong(int i)
  {
  a=b=c=i;
  cout<<"构造函数2"<<"\n";
  }
  hyong::~hyong()
  {
  cout<<"析构函数"<<"\n";
  }
  //复制构造函数
  hyong::hyong(const hyong &obj)
  {
  a=obj.a;
  b=obj.b;
  c=obj.c;
  cout<<"复制构造函数"<<"\n";
  }
  //按值传递对象
  void hyong::h(hyong k)
  {
  cout<<"按值传递对象"<<k.a<<k.b<<"\n";
  }
  //返回值为对象
  hyong hyong::f()
  {
  hyong kk(5);
  return kk;
  } 

析构函数
1、不管类是否定义了自己的析构函数,编译器都自动执行类中非static数据成员的析构函数。

2、如果类需要析构函数,则他也需要赋值操作符和复制构造函数。,这个规则常称作三法则。

3、一般而言,析构函数可以执行任意操作,该操作时类设计者希望在该类对象的使用完毕之后执行的。

4、合成析构函数按对象创建时的逆序撤销每个非static成员。

5、合成析构函数并不删除指针成员所指向的对象。

6、析构函数没有返回值,没有形参。因为不能指定任何形参,所以不能重载析构函数。

7、即使我们编写了自己的析构函数,合成析构函数依然运行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值