我们先来读一小段代码吧,从而引出几个概念:
template <class T>
class PFArray
{
public:
PFArray();
PFArray(int capacityValue );
PFArray(const PFArray& copyArray);
void addElement(int element);
bool isfull() const {return (used==capacity);}
int getCapacity() const {return capacity;}
int getUsedSize() const {return used;}
void emptyArray() {used = 0;}
void print() const;
bool isEqual(const PFArray & array1, const PFArray & arry2);
//重载赋值操作
PFArray & operator = (const PFArray &rightSide);
private:
T * a;
int capacity;
int used;
}
1、常引用调用参数 ,常类成员函数
首先,C++的一个优势,引用调用方式,比传值调用 方式效率高。
(1)传值调用时形参是一个局部变量,并使用实参来初始化。那么在函数被调用时,程序中相当于有两个实参的副本。而引用则是实参的一个别名,因此程序中只有实参一个副本。这种情况对于简单的数据类型,效率上的区别可以忽略不计。但是对于结构或类型来说,则不可小视了。
(2)注意传值调用时形参是一个局部变量的问题,在考虑传参方式时要慎重。
(3)如果在引用调用时,函数不需要改变参数的值,那么可以对不需要改变的参数用const进行标记,以便让编译器知道参数 不能被改变。如:const PFArray &array1,该方式即为常引用调用。
(4)当成员函数不会修改调用对象的值时,也可以用const来标记该函数。
(5)const要么不使用,要么应该使用的地方都用。如一个类类型使用了const参数修饰,那么在所有在函数调用中不会改变该类型参数的函数,都应该以const修饰。
2. 重载赋值操作符。
PFArray & operator = (const PFArray &rightSide);
赋值操作符实际上返回的是一个引用。为什么要重载赋值操作符呢?这就涉及到的浅复制和深复制的问题。
如:PFArray list_a(10), PFArray list_b(20);
list_a = list_b;
如果这里没有重载复制操作符,会使用默认的赋值操作符来执行它。即简单地将数据成员进行复制,包括将list_a.a = list_b.a。但是,a指向的是一个动态数组,即内存中的地址,进行简单的赋值之后,list_a.a和list_b.a指向了同一段内存。二者其一改变,另一必会跟着改变。
而我们希望能够产生完全独立于其右边变量的副本。所以进行运算符重载。
(1)浅复制:
在一个赋值操作符中的重载或拷贝构造函数中,如果函数的代码仅仅是将成员变量的值从一从此对象复制到另一个对象中,这种方式称为浅复制。默认的赋值操作符和拷贝构造函数执行的都是浅复制。
浅复制可以用于类中不包含指针或动态分配的数据。
(2)深复制:
如果类中包含指针或动态数组的成员变量,那么需要自己定义这样的赋值函数,重新分配内存,拷贝数据。以产生两个独立的副本
3. 拷贝构造函数
再定义拷贝构造函数的目的和上面刚刚提到的是一样的。
PFArray(const PFArray& copyArray);
在需要产生一个对象的副本的时候,就会自动调用复制构造函数。在下面3种情况下,拷贝构造函数会被调用:
(1)当声明一个类的对象时,使用另一个对象对它进行初始化
(2)当一个函数返回值为类类型时
(3)当一个类类型的实参传递给函数中的传值调用参数时。