Chinaunix首页 | 论坛 | 博客
  • 博客访问: 64649
  • 博文数量: 43
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 420
  • 用 户 组: 普通用户
  • 注册时间: 2014-06-27 15:04
个人简介

记录,分享

文章分类

全部博文(43)

文章存档

2017年(24)

2015年(1)

2014年(18)

我的朋友

分类: C/C++

2017-03-16 10:56:57

1. 复制构造函数

(1)复制构造函数具有单个形参,该形参是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式地调用赋值构造函数。当将该类型的对象传递给函数,或从函数返回该类型的对象时,将隐式使用复制构造函数,得到对象的副本。

(2)复制构造函数可用于
  • 根据另一个同类型的对象显式或隐式初始化一个对象
  • 复制一个对象,将它作为实参传递给一个函数
  • 从函数返回时复制一个对象
  • 初始化顺序容器中的元素
  • 根据元素初始化式列表初始化数组元素。

(3)对于类类型对象的初始化:直接初始化( A a(...); )直接调用与实参匹配的构造函数,而复制初始化( B b = B(...) ;)总是先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象。(注意,b1 = b2 称为赋值,与初始化不同)

(4)当使用表示容量的单个形参n来初始化容器container时,编译器首先调用T类型的默认构造函数创建一个临时值来初始化容器,然后使用复制构造函数将临时值复制到container的每个元素。
(5)当我们没有定义复制构造函数时,编译器会为我们合成一个复制构造函数。它对每个非static数据成员调用复制构造函数进行复制,将新对象初始化为原来的副本。与合成的默认构造函数不同,即使我们定义其他构造函数,编译器也会合成复制构造函数。
(6)类类型成员函数使用该类复制构造函数进行复制。数组成员的复制是个例外,虽然不能复制数组,但一个类如果有数组成员,则合成复制构造函数将复制数组——对数组的每个元素使用复制构造函数进行复制。
(7)只包含类类型成员或内置类型(不包含指针)成员的类,无需显式地定义复制构造函数。拥有指针数据成员的类可能需要显式定义复制构造函数。
(8)为了禁止复制,必须显式地声明复制构造函数为private,如iostream类



2.赋值操作符

(1)重载操作符是一些函数,名字以operator开头,后面跟着操作符号。操作符函数有一个返回值和一个形参表。
(2)赋值是二元操作符,同时它又必须是类的成员函数,因此它有一个形参,对应右操作数,this绑定到指向左操作数的指针。赋值操作符返回对同一类类型的引用。
(3)合成赋值操作符与合成复制构造函数类似:它按声明的顺序逐个给成员赋值,右操作数对象的每个成员赋值给左操作数的每个相应成员。对于数组,给数组每个元素赋值。
(4)一般而言,如果一个类需要赋值构造函数,它也会需要赋值操作符。



3.析构函数
(1)何时调用析构函数? 撤销类对象时自动调用析构函数:a.自动变量在超出作用域时自动撤销 ;b. 动态分配的对象在delete指向它的指针时撤销。
撤销一个容器时(标准库容器或者内置数组),会按逆序逐个运行容器内对象的析构函数,

(2)三法则:如果一个类需要析构函数,则它也需要复制构造函数和赋值操作符

(3)与复制构造函数和赋值操作符 不同 ! 编译器总是会为类合成一个析构函数,它按所有成员创建顺序的逆序调用各成员的析构函数。即使我们编写了自己的析构函数,合成析构函数仍然会在自己编写的析构函数执行完后执行(总会执行一次)!!!

(4)析构函数不能指定任何形参,也不能重载。
(5)继承结构中析构的次序:按照与构造函数相反的次序析构

【TIPS】
ClassA a1 = ClassA("hehe",1);  //复制初始化(先调用相应构造函数生成临时对象,再调用复制构造函数将临时对象复制到要生成的对象)
ClassA a2 = "hehe";  //复制初始化(先调用相应构造函数生成临时对象,再调用复制构造函数将临时对象复制到要生成的对象)
ClassA a3 = a2;  //复制初始化(调用复制构造函数将a2复制到要生成的对象)
ClassA a4("hehe");  //直接初始化(调用相应构造函数)
ClassA a5;  //直接初始化(调用默认构造函数);
a4 = a1;  //赋值,调用ClassA的赋值操作函数
a4 = "hehe";  //赋值,先调用相应构造函数生成临时对象,再调用赋值操作函数将临时对象的各成员赋值给要生成的对象


test.cc : 

#include
#include
#include
#include "ctest.h"
using namespace std;
void func0(){
 list l;
 for(int i=0;i<10;i++){
  ctest ct(i);
  l.push_back(ct);
 }
}
void func1(){
 vector v;
 for(int i=0;i<10;i++){
  ctest ct(i);
  v.push_back(ct);
 }
}
void func2(){
 ctest c1(1);
 ctest c1_;
 c1_ = c1;
}
void func3(){
 ctest c1(1);
 ctest c1_ = c1;
}
int main(int argc, char **argv) {
}

ctest.h :

#ifndef CTEST_H_
#define CTEST_H_
class ctest { 
private :
 int i;
public:
 ctest();
 ctest(int i);
 ctest(const ctest &c);
 ctest & operator=(const ctest &rv);
 virtual ~ctest();
};
#endif /* CTEST_H_ */


ctest.cc

#include "ctest.h"
#include
using namespace std;
ctest::ctest() {
 cout<<"construct"<
}
ctest::ctest(int i):i(i){
 cout<<"construct ["<
}
ctest::~ctest() {
 cout<<"destruct ["<
}
ctest::ctest(const ctest &c):i(c.i){
 cout<<"copy-constructor ["<
}
ctest & ctest::operator=(const ctest &rv){
 cout<<"assign operator ["<
 i = rv.i;
 return *this;
}



阅读(388) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~