C++中类对象的初始化与赋值的区别
C++中对象的初始化与赋值操作符是有区别。这一点在在理解,拷贝构造函数与赋值操作符的实现上是很重要的。
在C++ (C)变量的使用原则,总是先定义后使用。而基本类型的变量的初始化和赋值几乎没有区别的。
定义一个变量的过程:<1>定义声明 <2> 初始化. (#之所以称之为定义声明,还有连接性性声明如extern 这种外部连接性的声明,是没有内存分配的只是起到连接性的标志)
对于基本类型的变量的定义:
<1> 定义声明: 编译系统根据该变量的类型分配内存空间,此时变量的值由分配的内存空间的内容决定,此时变量的值时无用的、不确定、随机的的垃圾值,几乎没有用!
<2> 初始化;给变量一个确定的值。
<3> 赋值: 将有确定值得变量指派一个新的确定的值。
int b; //定义声明;
int a = 100; //定义声明以及初始化;
a = 200; //赋值操作
可见,基本类型的初始化与赋值几乎没有区别; 而对象类型的变量初始化与赋值又是怎样的呢?
类对象的初始化与赋值:声明的类对象变量总是被初始化的, 因为总有构造函数被调用,使其具有一个确定的值。
//声明类对象变量的过程:
<1> 分配空间;
< 2> 初始化: 可能的初始化情形: (a) 构造函数初始化; (b) 拷贝构函数初始化:用一个对象初始化另一个对象
<3> 赋值操作: 赋值操作只发生在初始化后的对象变量。使用赋值操作符进行赋值操作,在赋值操作符的实现中,注意变量的自我赋值的情形。
即使在变量声明时使用了=操作符,其实也是初始化操作。
构造函数只用于初始化,而拷贝构造函数只用于用对象初始化另一个为初始化的对象。
赋值操作,通过赋赋值操作符的实现的。
举例:
#include <iostream>
using namespace std;
template<class T>
class Array {
int size;
T *data;
public:
Array():size(0), data(0) {}
Array(int n):size(n), data(new T[n]) {}
Array(const Array& a):size(a.size){
data = new T[size];
for(int i=0; i<size; ++i) data[i] = a.data[i];
}
Array& operator=(const Array& a) {
if(&a != this) {
if(data) delete[] data;
size = a.size;
data = new T[size];
for(int i=0; i<size; ++i) data[i] = a.data[i];
}
return *this;
}
const T& operator[](int i) const{
return data[i];
}
T& operator[](int i){
return data[i];
}
~Array() {
if(data) delete[] data;
}
};
int main()
{
Array<int> a(10);
for(int i = 0; i<10; ++i) {
a[i] = i;
}
Array<int> b = a;
for(int i = 0; i<10; ++i) {
cout << b[i] << endl;
}
return 0;
}
当有资源分配,(动态内存分配时),拷贝构造函数、赋值操作符、析构函数三者缺一不可!
拷贝构造函数用于深拷贝,赋值操作符用于旧资源的释放,同时完成新资源的分配与赋值,析构函数对象的生命周期过期后,释放资源!
总之拷贝构造函数只用于初始化对象; 而赋值操作符用于对已初始化的对象进行赋值。