//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 第十三章的更多相关文章

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

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

  2. C++ Primer : 第十三章 : 动态内存管理类

    /* StrVec.h */ #ifndef _STRVEC_H_ #define _STRVEC_H_ #include <memory> #include <string> ...

  3. C++ Primer : 第十三章 : 拷贝控制示例

    /* Message.h */ #ifndef _MESSAGE_H_ #define _MESSAGE_H_ #include <iostream> #include <strin ...

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

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

  5. C++ Primer : 第十三章 : 拷贝控制之拷贝、赋值与销毁

    拷贝构造函数 一个构造函数的第一个参数是自身类类型的引用,额外的参数(如果有)都有默认值,那么这个构造函数是拷贝构造函数.拷贝构造函数的第一个参数必须是一个引用类型. 合成的拷贝构造函数   在我们没 ...

  6. 【C++ Primer 第十三章】4. 拷贝控制示例

    拷贝控制示例 #include<iostream> #include<string> #include<set> #include<vector> us ...

  7. C++ Primer Plus学习:第十三章

    第十三章 类继承 继承的基本概念 类继承是指从已有的类派生出新的类.例: 表 0-1 player.h class player { private: string firstname; string ...

  8. 【C++】《C++ Primer 》第十三章

    第十三章 拷贝控制 定义一个类时,需要显式或隐式地指定在此类型地对象拷贝.移动.赋值和销毁时做什么. 一个类通过定义五种特殊的成员函数来控制这些操作.即拷贝构造函数(copy constructor) ...

  9. PRML读书会第十三章 Sequential Data(Hidden Markov Models,HMM)

    主讲人 张巍 (新浪微博: @张巍_ISCAS) 软件所-张巍<zh3f@qq.com> 19:01:27 我们开始吧,十三章是关于序列数据,现实中很多数据是有前后关系的,例如语音或者DN ...

随机推荐

  1. 20145317彭垚 《Java程序设计》第10周学习总结

    20145317彭垚 <Java程序设计>第10周学习总结 教材学习内容总结 网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网 ...

  2. Java IO包装流如何关闭?

      问题: (1)JAVA的IO流使用了装饰模式,关闭最外面的流的时候会自动调用被包装的流的close()方吗? (2)如果按顺序关闭流,是从内层流到外层流关闭还是从外层到内存关闭? 问题(1)解释: ...

  3. VS小技巧

    1."清理解决方案":在对程序进行分发.上传时时常需要压缩解决方案文件夹,这时如果还嫌文件太大,可以在VS里右键解决方案---清理解决方.完成后,则该解决方案下的所有项目的将所有中 ...

  4. 转: svn合并分支到trunk

    http://sepcot.com/blog/2007/04/svn-merge-branch-trunk SVN: Merging a Branch into Trunk   This is mor ...

  5. 创建podSpec,使用pod管理第三方库

    提要: podfile文件会先读取.podspec文件,根据.podspec文件的指向来下载第三方库到项目中. 本文先通过一.二.三项,这三个步骤讲解了如何建立一个.podspec文件在本地.coco ...

  6. iOS 获取当前时间 年、月、日、周几

    NSDate * nowDate = [NSDate new]; NSCalendar *calendar = [NSCalendar currentCalendar]; NSUInteger uni ...

  7. sql server 2008语句中的go有什么用?

    GO表示一个批处理的结束, SQLSERVER遇到Go以后就会将GO之前的语句作为一整批进行处理你在SSMS里执行的时候, 通常加不加都可以,但是如果实在SQLCMD下执行, GO就是一个执行命令了另 ...

  8. jQuery动态对表格Table进行添加或删除行以及修改列值操作

    jQuery,不仅可以以少量的代码做很多操作,而且兼容性好(各种浏览器,各种版本). 下面用jQuery动态对表格Table进行添加或删除行以及修改列值操作 1.jQuery代码 <script ...

  9. iOS开发中 在MRC中让某些类使用ARC编译 或者相反

    如果你的工程是MRC 想让某些类使用ARC进行编译的话 那么需要在Build Phases中Complile Sourse 把该类后面 写上如下命令:-fobjc-arc  反之 写上如下命令:-fn ...

  10. https://www.zhihu.com/question/52020960#answer-47024535

    https://www.zhihu.com/question/52020960#answer-47024535