简单类

特殊成员函数

特殊成员函数与普通函数、运算符重载函数的一个显著的区分方法就是——没有返回值。

C++98必要组成:构造函数、拷贝构造函、赋值构造函数、析构函数。

C++11 :多了两个——移动构造函数、移动赋值构造函数

编译器会自动生成上述特殊成员函数。

默认构造函数:编译器生成的无参数构造函数。只要程序猿定义了有参构造函数,编译器就不会再提供无参构造函数了,所以为了防止出错,在显示定义有参构造函数前,要先定义一个无参构造函数。

构造函数分三类:无参构造函数,有参构造函数

有参构造函数可分为:转换构造函数、普通构造函数

转换构造函数部分初始化了成员,普通构造函数所有成员的初始化则需要由程序员提供。

在程序员未提供构造函数时,编译器会提供默认的无参构造函数。

与构造函数相关的关键字

noexcept

异常 noexcept 在函数的后面加上noexcept,代表这个函数不会抛出异常,如果抛出异常程序就会终止。使用 noexcept 表明函数或操作不会发生异常,会给编译器更大的优化空间。然而,并不是加上noexcept就能提高效率。

以下情形鼓励使用noexcept,不出意外noexcept只用于这三种函数:

1 移动构造函数(move constructor)

2 移动分配函数(move assignment)

3 析构函数(destructor)

explicit

explicit 关闭隐式类型转换,该关键字只用于转换构造函数

什么时候会发生隐式类型转换:赋值操作”=”且没有类型转化关键字的时候。比如double a=1就发生了int到double的隐式类型转换。

转换构造函数

把普通类型转化为类类型。其结构同有参构造函数一样,只不过部分参数被默认初始化了。

 explicit Complex(double real): m_real(real), m_imag(0.0){ } //把double类型转化为complex类型

 Complex(double real): m_real(real), m_imag(0.0){ } //区别在于complex a=2.0 是合法的,因为进行了隐式类型转化;加了explicit后,complex a=2.0语法错误,因为不能进行隐式类型转换,正确的格式为 complex a = complex(2.0)

类型转换函数

普通类型到类类型转换,类型转换函数结构与重载运算符类似,重载int等关键字。与一般运算符重载不同的是,类放在关键字后的()里。

class A

    {

    public:

        int a;

        A() {}

        explicit A(int a) :a(a) {}

        operator int()

        {

            return a;

        }

};

int main()

{

    A test(3);

    //用法1

    int d = test;

    //用法2

    int c = 2 + int(test);

    cout << d << endl;//3

    cout << c << endl;//5

    return 0;

}

类和类之间的类型转换

通过转换构造函数实现,与普通类型到类类型不同的是:1、编译器不提供隐式类型转换;2、未初始化的成员变量不一定只有一个,可能有多个。

=delete

C++11 中,可在想要 “禁止使用” 的特殊成员函数声明后加 “= delete”。比如编译器会生成多种构造函数,对于用不到的构造函数,后面添加delete即可。

=default

只要显式定义了任意一个特殊成员函数,该类就不属于POD类型了。但在显式定义的特殊成员函数后加上=default,该类就仍然是POD类型

为什么要区分出POD

POD,是Plain Old Data的缩写,普通旧数据类型,是C++中的一种数据类型概念。POD类型与C编程语言中使用的类型兼容,POD数据类型可以使用C库函数进行操作,也可以使用std::malloc创建,可以使用std::memmove等进行复制,并且可以使用C语言库直接进行二进制形式的数据交换。

什么是POD类型

当类或结构体同时满足如下几个条件时是普通类型:

 没有虚函数或虚基类;

 由C++编译器提供默认的特殊成员函数(默认的构造函数、拷贝构造函数、移动构造函数、赋值运算符、移动赋值运算符和析构函数);故自定义构造函数加一个=default,该类才属于pod类型。

判断是否为POD的方法

C++ 给定对象类型取决于其特定的内存布局方式,一个对象是普通、标准布局还是 POD 类型,可以根据标准库函数模板来判断:

#include<type_traits>

1)is_trivial<T>

2)is_standard_layout<T>

3)is_pod<T>

调用时机

什么时候调用构造函数

声明类对象时调用构造函数,若声明时未初始化,则调用默认构造函数;若在声明时初始化,则调用相应的初始化构造函数。

 class demo *ptr=new(demo a);//调用默认构造函数

 class demo a=1;//调用类型转换构造函数

 demo a(1);//调用有参构造函数

 初始化形参时调用拷贝构造函数或者有参构造函数

什么时候调用析构函数

销毁类时调用析构函数

比如:delete时、离开函数作用域时、多线程下呢?

默认析构函数的缺陷

如果程序员没有定义析构函数,系统将自动生成和调用一个默认析构函数,默认析构函数只能释放对象的数据成员所占用的空间,但不包括堆内存空间。

故凡是存在指针成员的类,一定要自定义析构函数。

拷贝构造函数

浅拷贝(图1)和深拷贝(图2)



如图,浅拷贝就是简单的赋值,指针也是赋值;深拷贝,指针成员不是简单赋值,而是重新分配一块内存。浅拷贝存在的问题就是释放其中任意一个对象,另一个对象会产生野指针。


如图,释放stu2后,stu1便产生了野指针。

类的内存分配



虚表、static成员函数、其它成员函数、数据成员

 首项存放虚函数表指针,包含虚函数的类才会有虚函数表,同属于一个类的对象共享虚函数表;

 接下来的内存空间依次存放数据成员;

 成员函数不占用类的内存空间,成员函数地址通过编译器找到,并没有存放在类中。static 成员变量和普通 static 变量一样,都在内存分区中的全局数据区分配内存,到程序结束时才释放。这就意味着,static 成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。

静态成员

1. 一个类中可以有一个或多个静态成员变量,所有的对象都共享这些静态成员变量,都可以引用它。注意,是共享,共享,共享,也即是只会占同一份静态存储空间。

2. static 成员变量和普通 static 变量一样,都在内存分区中的全局数据区分配内存,到程序结束时才释放。这就意味着,static 成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。而普通成员变量在对象创建时分配内存,在对象销毁时释放内存。根本原因是静态成员变量和对象的存储空间不同,是在不同的时期去分配的。

3. 静态成员变量必须初始化,而且只能在类体外进行。例如:int Point::count = 0;

虚表

虚表同static成员变量一样存放在全局数据区。

虚表指针并非指向虚表的表头,而是指向表头+16的位置。表头的前两个槽位(各占8个字节)。

然后存放type_info结构体指针,typeinfo内存放有与类的属性相关的信息。typeid(a)返回一个typeinfo对象,typeid(a).name()即typeinfo.name()返回a的类型名称。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351