赋值符常常初学者的混淆。这是毫无疑问的,因为’=’在编程中是最基本的运算符,可以进行赋值操作,也能引起拷贝构造函数的调用。
class Person{ friend ostream& operator<<(ostream& os,const Person& person){ os << "ID:" << person.mID << " Age:" << person.mAge << endl; return os; } public: Person(int id,int age){ this->mID = id; this->mAge = age; } //重载赋值运算符 Person& operator=(const Person& person){ this->mID = person.mID; this->mAge = person.mAge; return *this; } private: int mID; int mAge; }; //1. =号混淆的地方 void test01(){ Person person1(10, 20); Person person2 = person1; //调用拷贝构造 //如果一个对象还没有被创建,则必须初始化,也就是调用构造函数 //上述例子由于person2还没有初始化,所以会调用构造函数 //由于person2是从已有的person1来创建的,所以只有一个选择 //就是调用拷贝构造函数 person2 = person1; //调用operator=函数 //由于person2已经创建,不需要再调用构造函数,这时候调用的是重载的赋值运算符 } //2. 赋值重载案例 void test02(){ Person person1(20, 20); Person person2(30, 30); cout << "person1:" << person1; cout << "person2:" << person2; person2 = person1; cout << "person2:" << person2; } //常见错误,当准备给两个相同对象赋值时,应该首先检查一下这个对象是否对自身赋值了 //对于本例来讲,无论如何执行这些赋值运算都是无害的,但如果对类的实现进行修改,那么将会出现差异; //3. 类中指针 class Person2{ friend ostream& operator<<(ostream& os, const Person2& person){ os << "Name:" << person.pName << " ID:" << person.mID << " Age:" << person.mAge << endl; return os; } public: Person2(char* name,int id, int age){ this->pName = new char[strlen(name) + 1]; strcpy(this->pName, name); this->mID = id; this->mAge = age; } #if 1 //重载赋值运算符 Person2& operator=(const Person2& person){ //注意:由于当前对象已经创建完毕,那么就有可能pName指向堆内存 //这个时候如果直接赋值,会导致内存没有及时释放 if (this->pName != NULL){ delete[] this->pName; } this->pName = new char[strlen(person.pName) + 1]; strcpy(this->pName,person.pName); this->mID = person.mID; this->mAge = person.mAge; return *this; } #endif //析构函数 ~Person2(){ if (this->pName != NULL){ delete[] this->pName; } } private: char* pName; int mID; int mAge; }; void test03(){ Person2 person1("John",20, 20); Person2 person2("Edward",30, 30); cout << "person1:" << person1; cout << "person2:" << person2; person2 = person1; cout << "person2:" << person2; }
如果没有重载赋值运算符,编译器会自动创建默认的赋值运算符重载函数。行为类似默认拷贝构造,进行简单值拷贝。