【C++】拷贝,赋值与构造
拷贝,赋值与构造
文章目录
- 拷贝,赋值与构造
- 1. 拷贝构造函数/合成拷贝构造函数(copy constructor)
- 2. 拷贝赋值运算符
- 3. 析构函数
1. 拷贝构造函数/合成拷贝构造函数(copy constructor)
1.1 定义:复制构造函数是一个构造函数,它的第一个参数是对类类型的引用,任何附加参数都有默认值。
1.2 如下情况使用:
- case 1:使用 = 定义变量
- case 2: 将对象作为参数传递给非引用类型的参数
- case 3: 从具有非引用返回类型的函数返回一个对象
- case 4: 括号初始化数组中的元素或聚合类的成员
- case 5:一些类类型还为它们分配的对象使用复制初始化。
1.3 形如下:
拷贝构造函数的第一个参数必须是类的引用类型,拷贝构造函数在几种情况下P265会被隐式引用,因此,通常不应该不应该是 explicit 的。
class Foo{public: Foo();Foo(const Foo& obj);//拷贝构造函数
}
1.4 解释Sales_data::Sales_data(Sales_data rhs);
拷贝构造函数用来初始化非引用类类型参数,这一特性解释为什么拷贝构造函数自己的参数必须是引用类型。
如上,如果这样声明,调用将永远不会成功调用复制构造函数,Sales_data rhs 是实际的参数(实参),因此,我们需要使用复制构造函数来复制参数,但是要复制参数,我们又将需要调用复制构造函数,如此无限期地陷入死循环,依此类推。
1.5 即使我们自己定义拷贝构造函数,编译器也会为我们合成一个拷贝构造函数(synthesized copy constructor),对某些类来说,合成拷贝构造函数是用来阻止我们拷贝该类类型的对象。一般情况,合成拷贝构造函数会将其参数成员逐个拷贝到正在创建的对象中,编译器从给定对象中依次将每个非静态成员拷贝到正在创建的对象中。
1.6 ** What happens when we copy a StrBlob
? What about StrBlobPtrs
? **
// added a public member function to StrBlob and StrBlobPrts
long count() {return data.use_count(); // and wptr.use_count();
}// test codes in main()
StrBlob str({ "hello", "world" });
std::cout << "before: " << str.count() << std::endl; // 1
StrBlob str_cp(str);
std::cout << "after: " << str.count() << std::endl; // 2ConstStrBlobPtr p(str);
std::cout << "before: " << p.count() << std::endl; // 2
ConstStrBlobPtr p_cp(p);
std::cout << "after: " << p.count() << std::endl; // 2
当我们复制一个 StrBlob 时,shared_ptr 成员的 use_count 加一。
当我们复制一个 StrBlobPrts 时,weak_ptr 成员的 use_count 不会改变。(因为计数属于 shared_ptr)
1.7 假设 Point 是具有公共复制构造函数的类类型,请确定此程序片段中复制构造函数的每次使用:
Point global;
Point foo_bar(Point arg) // 1
{Point local = arg, *heap = new Point(global); // 2, 3*heap = local;Point pa[ 4 ] = { local, *heap }; // 4, 5return *heap; // 6
}
1.8 ex13_05_h,给定以下类,编写一个复制所有成员的复制构造函数。新增构造函数应该动态分配一个新字符串并复制 ps 指向的对象,而不是复制 ps 本身。
class HasPtr {
public:HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }
private:std::string *ps;int i;
};
#include <string>class HasPtr {
public:HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) { }
private:std::string *ps;int i;
};
2. 拷贝赋值运算符
2.1 重载运算符(overloaded operator),本质上是一个函数,由 operator + 自定义运算符组成
2.2 拷贝赋值运算符是什么?(复制赋值运算符是名为 operator= 的函数,它采用与类相同类型的参数。)
什么时候用?(发生赋值行为时候)
合成拷贝赋值运算符完成什么工作?(合成的复制赋值运算符,它会将使用该成员类型的复制赋值运算符的右侧对象的每个非静态成员分配给左侧对象的相应成员。)
什么时候会生成合成拷贝赋值运算符?(当类没有定义自己的类时,它会被合成。)
2.3 例子如下
class Foo{public: Foo();Foo& operator=(const Foo& obj);//赋值运算符
}
2.4 合成拷贝赋值运算符用来禁止该对象的赋值P450。
3. 析构函数
3.1 析构函数是什么?合成析构函数完成什么任务?什么时候生成合成析构函数?
析构函数是一个成员函数,类名前面加一个波浪号(~)。
类似拷贝构造函数和拷贝赋值操作运算符一样,对于某些类,合成析构函数被用来阻止该类型的对象被销毁。
编译器为任何没有定义自己的析构函数的类定义合成析构函数。
析构函数:在一个构造函数中**,成员的初始化是在一个函数体执行之前**完成,且按照他们在类中出现的顺序进行初始化。在析构函数中,首先执行函数体,然后销毁成员,成员的销毁顺序按照初始化的逆序进行。
在对象最后依次使用后,析构函数的函数体可以执行类设计者希望执行的任何收尾工作,通常,析构函数释放对象在生存期分配的所有资源。
3.1.1 什么时候调用析构函数?
无论何时一个对象被销毁,都会自动调用其析构函数
- 变量离开其作用域
- 当一个对象被销毁时,其成员被销毁
- 容器(stl vector等)被销毁时,其元素自动被销毁。
- 堆与动态分配的对象,当调用delete运算符删除其对应的指针时,其元素被销毁
- 堆与临时对象,当创建它的完整表达式结束时被销毁
3.2 当一个StrBlob对象被销毁时会发生什么? StrBlobPtr呢?
当销毁StrBlob对象时,动态对象的use_count将会减少(1)。如果没有shared_ptr指向该动态对象,则释放它
当一个StrBlobPter对象被销毁时,动态分配的对象将不会被释放。
3.3 Add a destructor to your HasPtr class from the previous exercises. ex13_11.h
#include <string>class HasPtr {
public:HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }HasPtr(const HasPtr &hp) : ps(new std::string(*hp.ps)), i(hp.i) { }HasPtr& operator=(const HasPtr &hp) {std::string *new_ps = new std::string(*hp.ps);delete ps;ps = new_ps;i = hp.i;return *this;}~HasPtr() { delete ps; } //deconstructor
private:std::string *ps;int i;
};
【C++】拷贝,赋值与构造相关推荐
- C++之Big Three:拷贝构造、拷贝赋值、析构函数探究
涉及到本文所讲知识点的博文: C++之析构函数探究 C++之常引用和浅拷贝探究 C++之一个函数链的简单例子(分文件实现) C++之Big Three:拷贝构造.拷贝赋值.析构函数探究 C++之操作符 ...
- c++三大函数:拷贝构造(copy ctor)、拷贝赋值(copy op)、析构函数(dtor)
Class的两个经典分类 Class without pointer member(s) complex Class with pointer member(s) string String clas ...
- 侯捷C++->三大函数:拷贝构造、拷贝赋值、析构
1.拷贝:如果类里带指针不能使用编译器给的那套赋值,仅仅是多了一个指针指向相同的内存(浅拷贝).(指针指向的内容不属于对象本身) 如果类带有指针,big three一定要写 2.拷贝构造:构造函数(函 ...
- 侯捷-C++面向对象高级开发(三大函数:拷贝构造,拷贝赋值,析构)
侯捷-C++面向对象高级开发(三大函数:拷贝构造,拷贝赋值,析构) 三大函数:拷贝构造,拷贝赋值,析构 第一个是拷贝构造,第二个是拷贝赋值 编译器有一套默认的东西实现这俩东西,可用到complex的实 ...
- C++之拷贝构造、拷贝赋值
拷贝构造 class Stu{public:int no;string name;int age; public:Stu(int no=10086, string name="jin&quo ...
- 5. 三大函数:拷贝构造 拷贝赋值 析构函数
String 类 拷贝构造和拷贝赋值应该怎么写 只要类里面带指针,一定不要用编译器的默认拷贝构造函数,一定要自己写 三个特殊函数 String (const char* cstr = 0); //构造 ...
- C++中的trivial和non-trivial构造/析构/拷贝/赋值函数及POD类型
在侯捷的<STL源码剖析>里提到trivial和non-trivial及POD类型,相关知识整理如下. trivial意思是无意义,这个trivial和non-trivial是对类的四种函 ...
- 【C++11智能指针】shared_ptr的初始化、拷贝构造和拷贝赋值、移动构造和移动赋值
文章目录 1.智能指针概述 2.shared_ptr的初始化 2.1 shared_ptr和new结合使用(直接初始化) 2.2 make_shared函数 3.shared_ptr的拷贝构造和拷贝赋 ...
- std::string的拷贝赋值研究
说明:以下涉及的std::string的源代码摘自4.8.2版本. 结论:std::string的拷贝复制是基于引用计数的浅拷贝,因此它们指向相同的数据地址. // std::string类定义 ty ...
最新文章
- python数据预测模型算法_如何对时间序列预测问题计算基准预测(python)
- pytorch loss function 总结
- 【随笔】express中间件系统的基本实现
- mysql设置不主动提交无效_关闭事务自动提交无效,回滚也无效
- git恢复删除前的版本
- 【算法分析与设计】经典排序算法实现
- Devexpress - office - 效果
- arch linux编译,ArchLinux内核编译与安装
- nodejs前端跨域访问
- Dubbo服务服务暴露之ProxyFactory Invoker
- .htaccess 让域名转向到别一域名
- android跳一跳作弊编程,跳一跳辅助器作弊刷分 微信跳一跳辅助工具(安卓/iOS苹果)-优基地...
- 2个或2个以上路由器串联上网,在同一网段
- ESET最近发现了一款新的Android勒索软件,它通过向受害者的手机的联系人列表发送恶意短信继续传播
- python 100days github_GitHub - shuipf/Python-100-Days: Python - 100天从新手到大师
- Kotlin GreenDao
- 开源CRM+SaaS云服务的生态模式能否撬动中国管理软件市场?
- 有哪些适合放在程序员办公桌上的高逼格物件?
- 读论文:BERT Pre-training of Deep Bidirectional Transformers for Language Understanding
- python异常处理结构的关键字_以下 Python 语言关键字在异常处理结构中用来捕获特定类型异常的选项是: ( )...
热门文章
- 5m 云服务器2核4g_华为云服务器2核4G 5M 248一年
- python周末列表的表示形式合并_Python 列表合并题
- python数据分析要学什么_python数据分析学什么?python数据分析入门
- oracle hot patch david,Oracle EBS使用adpatch工具打patch过程(hotpatch mode)
- php查询记录是否存在,php – 插入查询检查是否存在记录 – 如果不存在,插入它...
- 【C++】多线程(链式、循环队列)实现生产者消费者模式
- Git/Ctags/Vim/GDB基础笔记
- MySQL面试题 | 附答案解析(十)
- 使用Python、OpenCVImageMagick工具箱制作GIF动画
- 记录服务器连接jupyter notebook过程