1、一个类通过定义五种特殊的成员函数来控制此类型对象的拷贝、移动、赋值和销毁:拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符和析构函数。(拷贝、移动、析构)
 
2、拷贝和移动构造函数定义了当用同类型的另一个对象初始化本对象时做什么;拷贝和移动赋值运算符定义了讲一个对象赋予同类型的另一个对象时做什么;析构函数定义了当此类型对象销毁时做什么。这些操作统称为拷贝控制操作。
 
3、如果一个类没有定义所有这些拷贝控制成员,编译器会自动为它定义缺失的操作。
 
4、拷贝构造函数:构造函数的第一个参数是自身类类型的引用,并且任何额外参数都有默认值。
例子:

class Foo{
public:
Foo();//默认构造函数
Foo(const Foo&);//拷贝构造函数
}
5、类对象的拷贝初始化和直接初始化:前者使用拷贝构造函数,后者使用普通的函数匹配来选择与提供的参数最匹配的构造函数。除了使用“=”之外,非引用类型参数传递,返回非引用类型的对象等都会使用拷贝初始化。
 
6、拷贝赋值运算符重载了赋值(=)运算符,它的返回类型应该是一个指向其左侧运算对象的引用。
 Foo& operator=(const Foo&);
7、合成拷贝运算符由编译器合成,作用有两个:一是对于某些类用来禁止该类型对象的赋值;而是其他类将右侧运算对象的每个非static成员赋予作则运算对象的成员。下面代码等价于Sales_data的合成拷贝运算符:
   
Sales_data& //返回值
Sales_data::operator=(const Sales_data &rhs){//参数也是当前对象的引用类型
bookNo=rhs.bookNo;//调用string::operator=
units_sold=rhs.units_sold;//使用内置的int赋值
revenue=rhs.revenue;//使用内置的double赋值
return *this;//返回一个此对象的引用
}
 
6、拷贝函数和拷贝赋值运算符:如果一个对象已经定义了,然后给对象赋值,那么就会调用拷贝赋值运算符;如果是用于对象的初始化、非引用类型实参,非引用类型类返回值,那么就调用拷贝构造函数,参见下面的代码:
    1)类定义:

class Sales_data {
public:
Sales_data() = default;
Sales_data(const string &s, unsigned n, double p):bookNo(s),units_sold(n),revenue(p*n) {
}
Sales_data(const string &s):bookNo(s){} Sales_data(const Sales_data&);//拷贝构造函数,第一个参数为自身类类型的引用
Sales_data& operator=(const Sales_data &rhs);//拷贝赋值运算符,返回当前对象的引用,参数为另一个对象的引用 string isbn()const { return bookNo; }
Sales_data &combine(const Sales_data&);
private:
double avg_price()const {
return units_sold ? revenue / units_sold : ;
}
string bookNo;
unsigned units_sold = ;
double revenue = 0.0;
};
Sales_data& Sales_data::combine(const Sales_data &rhs) {
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
/* 拷贝构造函数的定义
** 拷贝构造函数应用于对象的拷贝初始化,函数的非引用参数传递和返回值
** 合成拷贝构造函数作用是阻止某些类的拷贝,或者将参数的成员逐个拷贝到正在创建的对象中
** 要记住它仍然是一个构造函数,是用来构造对象的
*/ Sales_data::Sales_data(const Sales_data &orig):bookNo(orig.bookNo),units_sold(orig.units_sold),revenue(orig.revenue) {
cout << "这是Sales_data的拷贝构造函数" << endl;
} /* 拷贝赋值运算符的定义
** 拷贝赋值运算符重载了赋值(=)运算符,在对象发生赋值操作的时候调用
** 合成的拷贝赋值运算符的作用是阻止某些类的赋值,或者将参数的成员赋予左侧运算对象的相应成员
** 返回值是当前对象的引用
*/
Sales_data& Sales_data::operator=(const Sales_data &rhs) {
cout << "这是Sales_data的拷贝赋值运算符" << endl;
bookNo = rhs.bookNo;
units_sold = rhs.units_sold;
revenue = rhs.revenue;
return *this;
}
    2)main函数
int main() {

    Sales_data sales_data_1{ "",, };//直接初始化,花括号
Sales_data sales_data_2("", , );//直接初始化,参数匹配
Sales_data sales_data_3 = sales_data_1;//拷贝初始化
Sales_data sales_data_4;
sales_data_4 = sales_data_1;//拷贝赋值运算符 //如果一个对象已经定义了,然后给对象赋值,那么就会调用拷贝赋值运算符;
//如果是用于对象的初始化、非引用类型实参,非引用类型类返回值,那么就调用拷贝构造函数。
return ;
}

[C++] 类的设计(2)——拷贝控制(1)的更多相关文章

  1. OOP3(继承中的类作用域/构造函数与拷贝控制/继承与容器)

    当存在继承关系时,派生类的作用域嵌套在其基类的作用域之内.如果一个名字在派生类的作用域内无法正确解析,则编译器将继续在外层的基类作用域中寻找该名字的定义 在编译时进行名字查找: 一个对象.引用或指针的 ...

  2. C++的那些事:类的拷贝控制

    1,什么是类的拷贝控制 当我们定义一个类的时候,为了让我们定义的类类型像内置类型(char,int,double等)一样好用,我们通常需要考下面几件事: Q1:用这个类的对象去初始化另一个同类型的对象 ...

  3. C++拷贝控制

    一.拷贝控制操作 ​ 当定义一个类时,显示或隐式地指定了此类型的对象在拷贝.赋值和销毁时所执行的操作,通过三个特殊的成员函数来控制这些操作,分别是拷贝构造函数,赋值运算符和析构函数.拷贝构造函数定义了 ...

  4. 【c++ Prime 学习笔记】第13章 拷贝控制

    定义一个类时,可显式或隐式的指定在此类型对象上拷贝.移动.赋值.销毁时做什么.通过5种成员函数实现拷贝控制操作: 拷贝构造函数:用同类型的另一个对象初始化本对象时做什么(拷贝初始化) 拷贝赋值算符:将 ...

  5. [C++]类的设计(2)——拷贝控制(拷贝控制和资源管理)

      1.类的行为分类:看起来像一个值:看起来想一个指针.     1)类的行为像一个值,意味着他应该有自己的状态.当我们拷贝一个像值的对象时,副本和原对象是完全独立的.改变副本不会对原有对象有任何影响 ...

  6. [C++]类的设计(2)——拷贝控制(阻止拷贝)

    1.阻止拷贝的原因:对于某些类来说,拷贝构造函数和拷贝赋值运算符没有意义.举例:iostream类阻止了拷贝,以避免多个对象写入或者读取相同的IO缓冲.   2.阻止拷贝的方法有两个:新标准中可以将成 ...

  7. C++类拷贝控制 深拷贝 浅拷贝

    普通类型对象之间的复制很简单,而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量,这篇文章将帮你理清C++类对象的拷贝方式 拷贝构造函数,拷贝赋值运算符 首先我们简单了解下默认的拷贝 ...

  8. C++ Primer : 第十三章 : 拷贝控制之对象移动

    右值引用 所谓的右值引用就是必须将引用绑定到右值的引用,我们通过&&来绑定到右值而不是&, 右值引用只能绑定到即将销毁的对象.右值引用也是引用,因此右值引用也只不过是对象的别名 ...

  9. C++ Primer : 第十三章 : 拷贝控制之拷贝控制和资源管理

    定义行为像值的类 行为像值的类,例如标准库容器和std::string这样的类一样,类似这样的类我们可以简单的实现一个这样的类HasPtr. 在实现之前,我们需要: 定义一个拷贝构造函数,完成stri ...

随机推荐

  1. Unity移动游戏加载性能和内存管理-学习笔记

    前言 正在学习Doctor 张.鑫大佬的移动游戏加载性能和内存管理,内容非常非常的干,所以我烧了很多开水,边喝边看,一边拿小本几做好笔记 本文只是关于前2章的内容笔记,关于各种资源的加载耗时 纹理资源 ...

  2. C#编写dll进行sql server数据库扩展储存过程

    一.编写C#函数文件 1.新建一个类库文件 备注:sqlserver 2008只能用.net3.5版本. 2.如有想加入强命名的话可如下步骤: 参考博文:https://blog.csdn.net/d ...

  3. Integer 使用==判断127和超过128的数据的区别

    Integer封装类型字数据当超过一定长度后,若使用==来判断数否相等,那么判断的结果是false; Integer的范围是超过128就是false. 对于所有封装类而言,建议使用equals来进行判 ...

  4. Scala 系列(九)—— 继承和特质

    一.继承 1.1 Scala中的继承结构 Scala 中继承关系如下图: Any 是整个继承关系的根节点: AnyRef 包含 Scala Classes 和 Java Classes,等价于 Jav ...

  5. C#数据结构_基本概念及线性表

    常见的4类数据结构: 1.集合. 2.线性结构.3.树形结构.4.图状结构. 数据结构(Data Structure)简记为 DS,是一个二元组,DS = (D,R) 其中:D 是数据元素的有限集合, ...

  6. Python中绘制场景热力图

    我们在做诸如人群密集度等可视化的时候,可能会考虑使用热力图,在Python中能很方便地绘制热力图. 下面以识别图片中的行人,并绘制热力图为例进行讲解. 步骤1:首先识别图像中的人,得到bounding ...

  7. Java NIO系列之[说在前面的话]

    在开始这个系列文章之前,先聊一些题外话,说说我为什么要写Java NIO这个系列技术文章(不看完会错失一个亿的),因为Java NIO并不像JVM,中间件源码那么有吸引力,但这个技术点是java的基础 ...

  8. P2050 [NOI2012]美食节 动态连边优化费用流

    题意 类似的一道排队等候,算最小总等待时间的题目. 思路 但是这道题的边数很多,直接跑会tle,可以动态加边,就是先连上倒数第一次操作的边,跑一遍费用流,然后对使用了倒数第一条边的点,连上相应的倒数第 ...

  9. HDU-2018多校7th-1011-Swordsman 附杜教fread代码

    HDU-6396 题意: 背景是打怪升级的故事,有k个不同属性的初始的能力值,每只怪物也有相同个数的能力值,你只能放倒k个能力值都比怪物大的,每放倒一个怪物,都可以得到相应的k个能力值. 思路: 根据 ...

  10. codeforces Round #389(Div.2)C Santa Claus and Robot(思维题)

    题目链接:http://codeforces.com/contest/752/problem/C 题意:给出一系列机器人的行动方向(机器人会走任意一条最短路径),问最少标记几个点能让机器人按这个 路径 ...