C++Primer 第十三章
//1.当定义一个类时,我们显示地或隐式地指出在此类型的对象(注意这里是此类型的对象,而不包括此类型的指针)拷贝,移动,赋值,销毁时做什么。一个类通过定义五种特殊的成员函数来控制这些操作:拷贝构造函数,拷贝赋值运算符,移动构造函数,移动赋值运算符,析构函数。
//当定义了五种特殊成员函数的其中一个的时候,一般也需要定义其他几个操作。
//拷贝构造函数的第一个参数必须是一个引用类型,若第一个参数不是引用类型则会造成逻辑错误:传值调用会产生一个临时对象,而此对象必须通过类的拷贝构造函数生成,所以会陷入死循环 //2.类的转换构造函数会自动调用。
CMyString(char *temStr) : str(temStr){printf("b0");}
CMyString str0 = "s0"; //这里将调用类的转换构造函数 //3.类的赋值运算符应该返回一个指向其左侧运算符对象的引用。返回左侧对象是为了能连续赋值,返回引用是为了提高效率。 //4.在一个析构函数中,首先执行函数体,然后按照成员初始化顺序逆序销毁成员。当在一个容器销毁其元素时,容器中的元素会自动执行其析构函数。
// 当指向一个对象的引用或指针离开作用域的时候,其指向类型的析构函数不会被调用。当一个动态分配的类类型指针,其被delete的时候,其指向类型的析构函数会被调用。
// 当一个类需要定义析构函数的时候,一般来说也需要定义其他的拷贝操作。
// 当一个类的析构函数被定义为不可访问的时候,不允许定义此类的对象。可以动态分配这种类型的对象,但是不能释放它。 //5.合成的拷贝控制成员可能是删除的:
A:如果类的某个成员的析构函数是删除或者不可访问的,则类的合成析构函数和类的合成拷贝构造函数被定义为删除的。
B:如果类的某个成员的拷贝构造函数是删除或不可访问的,则类的合成拷贝构造函数被定义为删除的。
C:如果类的某个成员的拷贝赋值运算符是删除或不可访问的,或是类有一个const或引用成员,则类的合成拷贝赋值运算符被定义为删除的。
D:如果类的某个成员的析构函数是删除或是不可访问的,或类有一个引用成员并且没有类内初始化器,或者类有一个const成员没有类内初始化器且类型没有指定默认构造函数,则该类的默认构造函数被定义为删除的。
总结:如果类的数据成员不能默认构造,拷贝,复制,销毁,则对应的成员函数将被定义为删除的。 //6.在private中声明类的拷贝构造函数等系列函数,并且不定义此类型函数,可以防止此类型对象被拷贝。注意点:不能定义,否则类的成员函数或者类的友员仍然能访问这些函数。 //7.赋值运算符通常组合了析构函数和拷贝构造函数的操作。注意点:如果将对象赋予其本身,赋值运算符必须能正常工作。 //8.通过&&来获得右值引用,右值引用有一个特殊性质:只能绑定到即将销毁的对象上(不能将右值引用直接绑定在左值上),来实现资源的移动。
// 左值持久,右值短暂。由于右值引用变量本身是一个左值变量,所以不能将右值引用绑定到右值引用对象上。
// 可以通过std::move函数来获得绑定到左值上的右值引用。此函数定义在头文件utility。声明在命名空间std中。
// move调用告诉编译器:我们有一个左值,但是我们希望像一个右值一样处理它。在调用move后就意味着承诺:对被调用变量,除了赋值或销毁外,我们将不再使用它。在调用std::move后,对被调用变量的值不能做任何假设。
// 使用move的时候,用如下方法:std::move。这样可以防止潜在的命名冲突。
// 当我们编写一个移动操作的时候,从一个对象移动资源而并不会销毁此对象,所以必须确保移后源对象进入一个有效的且可析构状态。
// 由于移后源对象具有不确定状态,所以当我们调用move后,必须绝对确认移后源对象没有其他用户。在代码中小心使用move可以极大的提高性能。 //9.当没有定义自己的移动操作的时候,通过函数匹配,会调用对应的拷贝操作版本。
// 只有当一个类没有定义任何自己版本的拷贝控制成员的时候,且类的每个非static成员都可以移动的时候,编译器才会定义移动控制成员。
// 当类定义了自己的移动操作后,会将其对应的默认拷贝操作定义为删除的。 //10.make_move_iterator:将普通迭代器转为移动迭代器。make_move_iterator定义在头文件iterator中。声明在命名空间std中。
allocator<unique_ptr<char>> allocStr;
auto pStr = allocStr.allocate();
vector<unique_ptr<char>> vecStr();
generate(vecStr.begin(), vecStr.end(), [](){return (unique_ptr<char>)new char();});
//uninitialized_copy(vecInt.begin(), vecInt.end(), pStr); //此句代码非法。unique_ptr对象是不可拷贝的
uninitialized_copy(make_move_iterator(vecStr.begin()), make_move_iterator(vecStr.end()), pStr); //正确执行,将vecStr的资源移动到了pStr所指向的内存中。 //11.如果一个成员函数同时提供拷贝和移动版本,也能提高性能。
// void push_back(_Ty&& _Val) :接受右值引用版本,来移动资源。对于存储unique_ptr类型的元素的容器的push_back操作就是调用此版本。
// void push_back(const _Ty& _Val) :此版本是拷贝版本。
C++Primer 第十三章的更多相关文章
- C++ Primer : 第十三章 : 拷贝控制之对象移动
右值引用 所谓的右值引用就是必须将引用绑定到右值的引用,我们通过&&来绑定到右值而不是&, 右值引用只能绑定到即将销毁的对象.右值引用也是引用,因此右值引用也只不过是对象的别名 ...
- C++ Primer : 第十三章 : 动态内存管理类
/* StrVec.h */ #ifndef _STRVEC_H_ #define _STRVEC_H_ #include <memory> #include <string> ...
- C++ Primer : 第十三章 : 拷贝控制示例
/* Message.h */ #ifndef _MESSAGE_H_ #define _MESSAGE_H_ #include <iostream> #include <strin ...
- C++ Primer : 第十三章 : 拷贝控制之拷贝控制和资源管理
定义行为像值的类 行为像值的类,例如标准库容器和std::string这样的类一样,类似这样的类我们可以简单的实现一个这样的类HasPtr. 在实现之前,我们需要: 定义一个拷贝构造函数,完成stri ...
- C++ Primer : 第十三章 : 拷贝控制之拷贝、赋值与销毁
拷贝构造函数 一个构造函数的第一个参数是自身类类型的引用,额外的参数(如果有)都有默认值,那么这个构造函数是拷贝构造函数.拷贝构造函数的第一个参数必须是一个引用类型. 合成的拷贝构造函数 在我们没 ...
- 【C++ Primer 第十三章】4. 拷贝控制示例
拷贝控制示例 #include<iostream> #include<string> #include<set> #include<vector> us ...
- C++ Primer Plus学习:第十三章
第十三章 类继承 继承的基本概念 类继承是指从已有的类派生出新的类.例: 表 0-1 player.h class player { private: string firstname; string ...
- 【C++】《C++ Primer 》第十三章
第十三章 拷贝控制 定义一个类时,需要显式或隐式地指定在此类型地对象拷贝.移动.赋值和销毁时做什么. 一个类通过定义五种特殊的成员函数来控制这些操作.即拷贝构造函数(copy constructor) ...
- PRML读书会第十三章 Sequential Data(Hidden Markov Models,HMM)
主讲人 张巍 (新浪微博: @张巍_ISCAS) 软件所-张巍<zh3f@qq.com> 19:01:27 我们开始吧,十三章是关于序列数据,现实中很多数据是有前后关系的,例如语音或者DN ...
随机推荐
- javascript中的eval()函数应用以及要点
eval是干嘛用的?eval是直接将一段字符串作为参数,交给JS引擎预编译器进行动态分析并执行代码.如下: //调试台输出,你可以理解为console.log,再不理解就理解成alert也没事 var ...
- Delphi出现“borland license information was found,but it is not valid for delphi”的错误,无法运行的解决方法
1) 删除文件: C:\documents and settings\<username>\.borland\registry.slm,如果在win8或在win7下,即C:\Users\H ...
- C#编程总结(四)多线程应用(进度条的编程问题)——转自http://www.cnblogs.com/yank/p/3232955.html
多线程应用 多线程应用很广泛,简单总结了一下: 1)不阻断主线程,实现即时响应,由后台线程完成特定操作2)多个线程,完成同类任务,提高并发性能3)一个任务有多个独立的步骤,多个线程并发执行各子任务,提 ...
- vm设置静态ip
1. 进入虚拟linux系统中,vim /etc/sysconfig/network-scripts/ifcfg-eth0,里面保留以下内容即可: DEVICE=eth0 //使用的网卡标识 BOOT ...
- phpcms 导航栏点击栏目颜色定位方法
另:一个栏目下面如果没有子栏目,那么它调用的模板就是列表页模板(及list_为前缀的模板):如果一个栏目下面有子栏目,那么它调用的就是栏目首页模板(category_为前缀的模板). 当你这个栏目添加 ...
- nodejs爬虫
前言 几个月之前,有同事找我要PHP CI框架写的OA系统.他跟我说,他需要学习PHP CI框架,我建议他学习大牛写的国产优秀框架QeePHP. 我上QeePHP官网,发现官方网站打不开了,GOOGL ...
- 【Android测试】【第一节】性能——CPU
◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/5065083.html 前言 本来打算写完全部的自动化测试之 ...
- Payoneer欧洲收款账户开通激活及使用-用于接收欧洲公司资金和欧元收款
在亚马逊国际平台的卖家往往会被问道需要美国(或者欧洲或者日本等)银行账户才能收款,这个政策个人认为是亚马逊对当地卖家的保护政策(大量的中国低价物美的卖家涌入会导致当地的卖家没有优势),二是当地税收政策 ...
- linux与linux,linux与windows之间用SSH传输文件
linux与linux,linux与windows之间用SSH传输文件linux与linux之间传送文件:scp file username@hostIP:文件地址 例: scp abc.txt ...
- ASP.NET 开发笔记1
1.GirdView 动态添加列 PostBack 后 模板列中的控件丢失的问题 http://blackboy51.blog.163.com/blog/static/511359122011910 ...