c++赋值构造函数为什么返回引用类型?

2014-11-24 12:14:44 · 作者: · 浏览: 1
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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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();
}