初始化对象数组的方案是,首先使用默认构造函数来创建数组元素,然后花括号中的构造函数将创建临时对象,然后将临时对象的内容拷贝到相应的元素中。因此,要创建类对象数组,则这个类必须有默认构造函数。
C++提供的默认拷贝构造函数和默认赋值函数工作的方法是:完成一个成员一个成员的拷贝,如果成员是类对象,则调用其拷贝构造函数或者默认拷贝构造函数。默认拷贝构造函数执行的是浅拷贝(“位拷贝”而非“值拷贝”)。当类成员里边有指针变量时,这两个默认的构造函数肯定会出错。
以类对象作为函数参数,调用该函数时将执行拷贝构造函数。
employee.h
#ifndef __EMPLOYEE_H
#define __EMPLOYEE_H
class employee
{
public:
employee();
employee(const employee& other);
employee(const char *nm);
~employee();
void display();
private:
char *name;
int id;
};
#endif
employee.cpp
#include "employee.h"
#include <iostream>
using std::cout;
using std::endl;
int uid = 0;
// 默认构造函数
employee::employee()
{
name = NULL;
id = 0;
cout << "this is default constructor" << endl;
}
// 拷贝构造函数
employee::employee(const employee& other)
{
name = new char[strlen(other.name) + 1];
strcpy(name, other.name);
id = other.id;
cout << "this is copy constructor" << endl;
}
// 有参构造函数
employee::employee(const char *nm)
{
name = new char[strlen(nm) + 1];
strcpy(name, nm);
id = ++uid;
cout << "this is parameter (const char *nm) constructor" << endl;
}
employee::~employee()
{
cout << "this is destructor" << endl;
if (name != NULL)
{
cout << "I will delete name" << endl;
delete name;
name = NULL;
}
}
void employee::display()
{
cout << "name is " << name << endl
<< "id = " << id << endl;
printf("name addr is %p\n", name);
}
main.cpp
#include "employee.h"
int main(int argc, char* argv[])
{
employee em1("zhang"); // 打印"this is parameter (const char *nm) constructor"
employee em2 = em1; // 打印"this is copy constructor"
employee em3; // 打印"this is default constructor"
em3 = em2; // 此处将调用默认的赋值函数[employee& operator=(const employee& other)]
em1.display();
em2.display();
em3.display();
// this is parameter (const char *nm) constructor
// this is default constructor
// this is default constructor
// this is destructor
// this is destructor
// this is destructor
employee ems[3] = {employee("zhao")};
return 0;
}
程序输出
this is parameter (const char *nm) constructor
this is copy constructor
this is default constructor
name is zhang
id = 1
name addr is 00032BC8
name is zhang
id = 1
name addr is 00032C30
name is zhang
id = 1
name addr is 00032C30
this is parameter (const char *nm) constructor // ems[0]
this is default constructor // ems[1]
this is default constructor // ems[2]
this is destructor // ems[2]
this is destructor // ems[1]
this is destructor // ems[0]
I will delete name
this is destructor // em3
I will delete name // 第一次释放00032C30的地址
this is destructor // em2,该对象的name和em3的name指向同一块内存地址
I will delete name // 第二次释放00032C30的地址,g++并没有报异常
this is destructor // em1
I will delete name