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

目录



0 前言


1 内置类型


2 自定义类型


3 结论


4 源码

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

c++赋值构造函数为什么返回引用类型?,码迷,mamicode.com

时间: 2024-08-09 16:49:22

c++赋值构造函数为什么返回引用类型?的相关文章

C++ 赋值构造函数的返回值到底有什么用?且返回值是否为引用类型有什么区别吗?

首先定义类Person class Person{ public: string name; Person()=default; //默认构造函数 Person(string nam):name(nam){} void operator=(const Person& p){ //赋值构造函数 this->name=p.name; } }; Person a("xiaoming"); Person b; cout<<b.name<<endl; //空

c++类大四个默认函数-构造函数 析构函数 拷贝构造函数 赋值构造函数

每个类只有一个析构函数和一个赋值函数,但可以有多个构造函数(包含一个拷贝构造函数,其它的称为普通构造函数).对于任意一个类A,如果不编写上述函数,C++编译器将自动为A 产生四个缺省的函数,例如: A(void);//缺省的无参数构造函数 A(const A&a);//缺省的拷贝构造函数 -A();//缺省的析构函数 A&operator=(const A &a);//缺省的赋值构造函数 1).“缺省的拷贝构造函数”和“缺省的赋值函数”均采用“位拷贝”而非“值拷贝”的方式来实现,倘

C++ 赋值函数为什么返回reference to *this?

赋值操作为什么要返回 reference to *this? 要弄清这个问题之前,先了解函数的返回值类型:返回值类型,返回引用类型 返回值类型:返回的是一个对象的副本. test operator= (const test &t) { ... cout << "赋值" << endl; return *this; } 当程序中出现test对象之间的赋值操作时, 调用 operator函数.当return *this的时候,会执行拷贝构造test(cons

为什么类的拷贝构造参数加引用、重载赋值函数的返回值和参数加引用

class string { public: string(const char *str=NULL); string(const string& str);     //copy构造函数的参数为什么是引用呢? string& operator=(const string & str); //赋值函数为什么返回值是引用呢?参数为什么是引用呢? ~string(); }; 下面我就给大家解释一下: class String1 { public: String1(const char*

C++ 为什么拷贝构造函数参数必须为引用?赋值构造函数参数也必须为引用吗?

之前写拷贝构造函数的时候,以为参数为引用,不为值传递,仅仅是为了减少一次内存拷贝.然而今天看到一篇文章发现自己对拷贝构造的参数理解有误. 参数为引用,不为值传递是为了防止拷贝构造函数的无限递归,最终导致栈溢出. 下面来看一个例子: class test { public: test() { cout << "constructor with argument\n"; } ~test() { } test(test& t) { cout << "

(copy)赋值构造函数的4种调用时机or方法

第一种调用方法: demo #include <iostream> using namespace std; class Text { public: Text() // 无参数构造函数 { m_a = 0; m_b = 0; cout << "无参数构造函数" << endl; } Text(int a) // 有参数构造函数 { m_a = a; m_b = 0; cout << "无参数构造函数" <<

赋值构造函数(重载赋值操作符)(c++常问问题二)

*什么是赋值构造函数(重载赋值操作符) 下面的代码演示了什么是赋值构造函数,如果不人为定义赋值构造函数,系统将默认给你分配一个浅拷贝的赋值构造函数(下面例子为深拷贝的赋值操作) class cat { public: //构造函数 cat():m_pMyName(NULL),m_unAge(0) { cout<<"cat defult ctor"<<endl; } //子类赋值构造函数(重载赋值操作符) cat& operator=(cat& o

构造函数的调用(其中不包括赋值构造函数)

1 #include<iostream> 2 3 using namespace std; 4 //解析和析构函数的调用 5 class Test 6 { 7 public: 8 Test() 9 { 10 cout<<"我是无参的构造函数\n\n"; 11 } 12 Test (int i) 13 { 14 t_a=i; 15 cout<<"i= "<<i<<endl; 16 cout<<&q

C++返回引用类型 指针的引用(转载)

C++返回引用类型A& a(){ return *this;} 就生成了一个固定地址的指针,并把指针带给你但A a() { return *this;}会生成一个临时对象变量,并把这个临时变量给你这样就多了一步操作当返回一个变量时,会产生拷贝.当返回一个引用时,不会发生拷贝,你可以将引用看作是一个变量的别名,就是其他的名字,引用和被引用的变量其实是一个东西,只是有了两个名字而已.问题的关键是,当你想要返回一个引用而不是一个拷贝时,你要确保这个引用的有效性,比如:int & fun() {