c++賦值構造函數爲何返回引用類型?

目錄

0 前言ios

1 內置類型c++

2 自定義類型函數

3 結論this

4 源碼spa

0. 前言

  c++默認賦值構造函數的返回值是引用類型,c++賦值運算符=的本意是返回左值的引用,咱們重載賦值構造函數的時候,返回值是否應該設爲引用類型呢? 按照《Effective C++》中第10條,最好是設爲引用類型。code

  本文,經過實驗來表述返回值是否爲引用類型的區別。htm

1. 內置類型

  int i= 1,     j=2,    k=3;blog

  • case1: k = j = i

    i == 1ip

  j == 1get

  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();
}

 

 此文章爲 '永無止境'(入駐一點號的媒體名稱)原創,特此聲明!

相關文章
相關標籤/搜索