//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. Rice Rock

    先翻译评分要点,然后一点点翻译程序实现过程 如何产生一堆岩石? rock_group = set([])#空集合,全局变量   rock_group.add(a_rock) 要画出来draw hand ...

  2. java 强制转换

    在java中强制类型转换分为基本数据类型和引用数据类型两种,这里我们讨论的后者,也就是引用数据类型的强制类型转换. 在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类转换成子类则需 ...

  3. 【转】Unity 之 移动设备的触控操作

    http://blog.csdn.net/anyuanlzh/article/details/18367941 这篇博文将简单的记录,如何用unity处理在移动设备上的触控操作.    iOS和And ...

  4. 如何在外网中访问自己在另一个局域网中的某个机器(SSH为例)

    UBUNTU 14.04 LTS 为例 如何在外网中访问自己在另一个局域网中的某个机器(SSH为例) 2013-05-01 16:02 2693人阅读 评论(0) 收藏 举报 情景描述: 计算机C1放 ...

  5. Java程序设计的基本原则

    Java程序设计的基本原则-1 1.面向对象 这是java编程里面大家公认的第一原则 2.优先使用对象组合而非类继承 3.分层 最典型的三层架构,表现层-->逻辑层-->数据层 表现层功能 ...

  6. css中textarea去掉边框和选中后的蓝色边框问题的解决方法

    我们在设计网页的输入框时,有时会遇到需要把textarea的边框去掉的问题,经过测试,下面的代码是可以的. textarea{ border: solid 0px; outline:none; }

  7. HIVE中的HQL操作

    1.字段查询 select empno,ename from emp; 2.过滤where,limit,distinct select * from emp where sal >2500; s ...

  8. XLAT转码:以DS:【BX+AL】为地址,提取存储器中的一个字节再送入AL

    data segment a db ,,,,,,,, b dw ;sum of a table db 11h,22h,33h,44h,55h,66h,77h,88h,99h ends code seg ...

  9. The Shortest Path in Nya Graph---hdu4725(spfa+扩点建图)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4725  有n个点,每个点都有一个层l[i],相邻层的边有一条无向带权边,权值为都为C,另外 ...

  10. cname和CDN

    http://blog.csdn.net/crazw/article/details/8986504 先说一下DNS的几个基本概念: 一. 根域 就是所谓的“.”,其实我们的网址www.baidu.c ...