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

时间:2023-03-09 02:29:12
c++赋值构造函数为什么返回引用类型?

目录

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 = , j = , k = ; k = j = i; cout << "\ti=" << i << endl; //
cout << "\tj=" << j << endl; //
cout << "\tk=" << k << endl; //
} void test_int2()
{
cout << "test_int2()" << endl;
int i = , j = , k = ; (k = j) = i; cout << "\ti=" << i << endl; //
cout << "\tj=" << j << endl; //
cout << "\tk=" << k << endl; //
} 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();
}

此文章为 '永无止境'(入驻一点号的媒体名称)原创,特此声明!