0. 前言 c++默認賦值構造函數的返回值是引用類型,c++賦值運算符=的本意是返回左值的引用,我們重寫賦值構造函數的時候,返回值是否應該設為引用類型呢? 按照《Effective C++》中第10條,最好是設為引用類型。 本文,通過實驗來表述返回值是否為引用類型的區別。 1. 內置類型 int i= 1, j=2, k=3; case1: k = j = i i == 1 j == 1 k == 1 case2: (k = j) = i i == 1 j == 2 k == 1 2. 自定義類型 People p1("p1"), p2("p2"), p3("p3"); case1: p3 = p2 = p1 使用默認賦值構造函數 p3 == p1 p2 == p1 返回引用的People p3 == p1 p2 == p1 不返回引用的People p3 == p1 p2 == p1 case2: (p3 = p2) = p1 使用默認賦值構造函數 p3 == p1 p2 == p2 返回引用的People p3 == p1 p2 == p2 不返回引用的People p3 == p2 p2 == p2 3. 結論: case1,是否返回引用沒有影響; case2,是否返回引用是有區別的,由於c++內置類型的賦值重載操作符是返回引用的,所以我們應該遵循規則,類的賦值構造函數返回引用類型。 4. 實驗源碼: 復制代碼 #include <algorithm> #include <cstdio> #include <cstdlib> #include <cwchar> #include <functional> #include <iostream> #include <iomanip> #include <iterator> #include <string> #include <vector> #include <memory> #include <sstream> #include <utility> using std::cout; using std::endl; using std::string; using std::vector; using std::stringstream; void test_int() { cout << "test_int()" << endl; int i = 1, j = 2, k = 3; k = j = i; cout << "\ti=" << i << endl; // 1 cout << "\tj=" << j << endl; // 1 cout << "\tk=" << k << endl; // 1 } void test_int2() { cout << "test_int2()" << endl; int i = 1, j = 2, k = 3; (k = j) = i; cout << "\ti=" << i << endl; // 1 cout << "\tj=" << j << endl; // 2 cout << "\tk=" << k << endl; // 1 } class People { public: People(const string &_name = "") : name(_name) {} People operator=(const People &_p) { name = _p.name; return *this; } string name; }; void test() { cout << "test(): not reference" << endl; cout << "\tp3=p2=p1" << endl; People p1("p1"), p2("p2"), p3("p3"); p3 = p2 = p1; cout << "\t\tp2.name=" << p2.name << endl; // p1 cout << "\t\tp3.name=" << p3.name << endl; // p1 } void test2() { cout << "test2(): not reference" << endl; cout << "\t(p3=p2)=p1" << endl; People p1("p1"), p2("p2"), p3("p3"); (p3 = p2) = p1; cout << "\t\tp2.name=" << p2.name << endl; // p2 cout << "\t\tp3.name=" << p3.name << endl; // p2 } class PeopleRef { public: PeopleRef(const string &_name = "") : name(_name) {} PeopleRef& operator=(const PeopleRef &_p) { name = _p.name; return *this; } string name; }; void test_ref() { cout << endl; cout << "test_ref(): reference" << endl; cout << "\tp3=p2=p1" << endl; PeopleRef p1("p1"), p2("p2"), p3("p3");; p3 = p2 = p1; cout << "\t\tp2.name=" << p2.name << endl; // p1 cout << "\t\tp3.name=" << p3.name << endl; // p1 } void test_ref2() { cout << "test_ref2(): reference" << endl; cout << "\t(p3=p2)=p1" << endl; PeopleRef p1("p1"), p2("p2"), p3("p3");; (p3 = p2) = p1; cout << "\t\tp2.name=" << p2.name << endl; // p2 cout << "\t\tp3.name=" << p3.name << endl; // p1 } class PeopleDefault { public: PeopleDefault(const string &_name = "") : name(_name) {} string name; }; void test_default() { cout << endl; cout << "test_default()" << endl; cout << "\tp3=p2=p1" << endl; PeopleDefault p1("p1"), p2("p2"), p3("p3"); p3 = p2 = p1; cout << "\t\tp2.name=" << p2.name << endl; // p1 cout << "\t\tp3.name=" << p3.name << endl; // p1 } void test_default2() { cout << "test_default2()" << endl; cout << "\t(p3=p2)=p1" << endl; PeopleDefault p1("p1"), p2("p2"), p3("p3"); (p3 = p2) = p1; cout << "\t\tp2.name=" << p2.name << endl; // p2 cout << "\t\tp3.name=" << p3.name << endl; // p1 } int main () { test_int(); test_int2(); test(); test2(); test_ref(); test_ref2(); test_default(); test_default2(); }