在侯捷的《STL源码剖析》里提到trivial和non-trivial及POD类型,相关知识整理如下。

trivial意思是无意义,这个trivial和non-trivial是对类的四种函数来说的:

  • 构造函数(ctor)

  • 复制构造函数(copy)

  • 赋值函数(assignment)

  • 析构函数(dtor)

简单来说,“平凡”意味着这些特殊的成员函数用很朴素的方式完成它们的工作。而”很朴素的方式“这个说法对不同的函数有不同的意义。

对默认构造函数和析构函数来说,“平凡”意味着什么也不做。

对拷贝构造函数和拷贝赋值函数来说,“平凡”意味着只做简单的内存拷贝。

如果至少满足下面3条里的一条:

  • 显式(explict)定义了这四种函数。

  • 类里有非静态非POD的数据成员。

  • 有基类。

那么上面的四种函数是non-trivial函数,比如叫non-trivial ctor、non-trivial copy…,也就是说有意义的函数,里面由一些必要的操作,比如类成员的初始化、释放内存等。

那个POD意思是Plain Old Data,也就是C++的内建类型或传统的C结构体类型。POD类型必然有trivial ctor/dtor/copy/assignment四种函数。

// 整个T是POD类型
class T
{// 没有显式定义ctor/dtor/copy/assignemt所以都是trivialint a; // POD类型
};// 整个T1是非POD类型
class T1
{T1() // 显式定义了构造函数,所以是non-trivial ctor{}// 没有显式定义dtor/copy/assignemt所以都是trivialint a;         // POD类型std::string b; // 非POD类型
};

对POD类型的一些补充:

POD 是英文中 Plain Old Data 的缩写,翻译过来就是 普通的旧数据 。POD 在 C++ 中是非常重要的一个概念,通常用于说明一个类型的属性,尤其是用户自定义类型的属性。

POD 属性在 C++11 中往往又是构建其他 C++ 概念的基础,事实上,在 C++11 标准中,POD 出现的概率相当高。因此学习 C++,尤其是在 C++11 中,了解 POD 的概念是非常必要的。

Plain :表示是个普通的类型

Old :体现了其与 C 的兼容性,支持标准 C 函数

在 C++11 中将 POD 划分为两个基本概念的合集,即∶平凡的(trivial) 和标准布局的(standard layout )。

一个平凡的类或者结构体应该符合以下几点要求:

1、拥有平凡的默认构造函数(trivial constructor)和析构函数(trivial destructor)。

平凡的默认构造函数就是说构造函数什么都不干。

  • 通常情况下,不定义类的构造函数,编译器就会为我们生成一个平凡的默认构造函数。

// 使用默认的构造函数
class Test {};
  • 一旦定义了构造函数,即使构造函数不包含参数,函数体里也没有任何的代码,那么该构造函数也不再是"平凡"的。

class Test1
{Test1();    // 程序猿定义的构造函数, 非默认构造
};

关于析构函数也和上面列举的构造函数类似,一旦被定义就不平凡了。但是这也并非无药可救,使用=default 关键字可以显式地声明默认的构造函数,从而使得类型恢复“平凡化”。

2、拥有平凡的拷贝构造函数(trivial copy constructor)和移动构造函数(trivial move constructor)。

  • 平凡的拷贝构造函数基本上等同于使用 memcpy 进行类型的构造。

  • 同平凡的默认构造函数一样,不声明拷贝构造函数的话,编译器会帮程序员自动地生成。

  • 可以显式地使用 = default 声明默认拷贝构造函数。

  • 而平凡移动构造函数跟平凡的拷贝构造函数类似,只不过是用于移动语义。

3、拥有平凡的拷贝赋值运算符(trivial assignment operator)和移动赋值运算符(trivial move operator)。

这基本上与平凡的拷贝构造函数和平凡的移动构造函数类似。

4、不包含虚函数以及虚基类。

  • 类中使用 virtual 关键字修饰的函数 叫做虚函数

class Base
{
public:Base() {}virtual void print() {}
};
  • 虚基类是在创建子类的时候在继承的基类前加 virtual 关键字修饰

语法:
class 派生类名:virtual 继承方式 基类名

示例代码:

class Base
{
public:Base() {}
};
// 子类Child,虚基类:Base
class Child : virtual public Base
{Child() {}
};

那这有什么用处呢?

如果这个类是trivial ctor/dtor/copy/assignment函数,我们对这个类进行构造、析构、拷贝和赋值的时候可以采用最有效率的方法,不调用无所事事的那些ctor/dtor等,而直接采用内存操作如malloc()、memcpy()等提高性能,这也是SGI STL内部干的事情。

比如STL的copy算法最基本的想法是这样的:

// 非POD重载指针数值
template << / span > class T > void copy(T *source, T *destination, int n, __false_type)
{// 省略异常处理for (; n > 0; n--, source++, destination++){// 调用source的拷贝构造函数constructor(source, *destination);}
}// POD重载指针数值
template << / span > class T > void copy(T *source, T *destination, int n, __false_type)
{// 省略异常处理memmove(source, destination, n);
}

当然实际的copy比这个复杂多了,有非常多的特化等,这个只是其中一方面而已。

C++中的trivial和non-trivial构造/析构/拷贝/赋值函数及POD类型相关推荐

  1. 《深度探索C++对象模型》读书笔记第五章:构造析构拷贝语意学

    <深度探索C++对象模型>读书笔记第五章:构造析构拷贝语意学 对于abstract base class(抽象基类),class中的data member应该被初始化,并且只在constr ...

  2. C++之拷贝构造、拷贝赋值

    拷贝构造 class Stu{public:int no;string name;int age; public:Stu(int no=10086, string name="jin&quo ...

  3. C++学习笔记day47-----C++98-继承中的构造函数,析构函数,拷贝构造函数,拷贝赋值函数,多重继承,虚继承

    继承中的构造函数 当通过一个子类创建一个新的对象时,编译器会根据子类在初始化表中指明的基类的初始化方式去调用基类相应的构造函数.如果子类的初始化表中,并没有指明基类的初始化方式,编译器将会调用基类的无 ...

  4. 【C++11智能指针】shared_ptr的初始化、拷贝构造和拷贝赋值、移动构造和移动赋值

    文章目录 1.智能指针概述 2.shared_ptr的初始化 2.1 shared_ptr和new结合使用(直接初始化) 2.2 make_shared函数 3.shared_ptr的拷贝构造和拷贝赋 ...

  5. C++之Big Three:拷贝构造、拷贝赋值、析构函数探究

    涉及到本文所讲知识点的博文: C++之析构函数探究 C++之常引用和浅拷贝探究 C++之一个函数链的简单例子(分文件实现) C++之Big Three:拷贝构造.拷贝赋值.析构函数探究 C++之操作符 ...

  6. 侯捷C++->三大函数:拷贝构造、拷贝赋值、析构

    1.拷贝:如果类里带指针不能使用编译器给的那套赋值,仅仅是多了一个指针指向相同的内存(浅拷贝).(指针指向的内容不属于对象本身) 如果类带有指针,big three一定要写 2.拷贝构造:构造函数(函 ...

  7. 侯捷-C++面向对象高级开发(三大函数:拷贝构造,拷贝赋值,析构)

    侯捷-C++面向对象高级开发(三大函数:拷贝构造,拷贝赋值,析构) 三大函数:拷贝构造,拷贝赋值,析构 第一个是拷贝构造,第二个是拷贝赋值 编译器有一套默认的东西实现这俩东西,可用到complex的实 ...

  8. 《深度探索C++对象模型》--5 构造析构拷贝 6 执行期语意学

     <深度探索C++对象模型>--5构造.析构.拷贝语意学 1.纯虚函数: (1)C++可以定义和调用一个纯虚函数,不过只可以静态调用,不可以由虚拟机制调用. 注意:pure virtu ...

  9. Effective C++学习笔记——构造/析构/拷贝运算

    条款9:决不再构造和析构过程中调用virtual函数,包括通过函数间接调用virtual函数. 应用:想在一个继承体系中,一个derived class被创建时,某个调用(例如生成相应的日志log)会 ...

最新文章

  1. MySQL的高级运用_MYSQL之SQL高级运用(帮助你高效率编程)
  2. 剖析Disruptor:为什么会这么快?(一)锁的缺点
  3. js中的对象类型与具体的对象
  4. 好文章,被架构师秒杀之后
  5. 2020/5/13号单词
  6. 如何使用QuickConnect远程访问Synology NAS
  7. python中函数的可变参数_Python中函数的参数定义和可变参数
  8. 10. 单例模式(singleton pattern)
  9. 方向余弦矩阵与四元数
  10. MySql安装版安装最新教程(附错误解决 )
  11. 使用命令修改dns服务器地址,Windows下使用命令行设置ip地址的DNS服务器
  12. java 中 枚举 大括号 用法
  13. windows server 2008安装配置web服务器
  14. 国内外快递公司名称一览表
  15. A detailed derivation for the Bias Variance tradeoff Decomposition
  16. 通达信V6.1分时数据文件格式分析
  17. Delphi文件正文提取开发组件--文件内容搜索的高效工具
  18. matlab解二阶微分方程组ode,MATLAB解含参数方程、矩阵方程、二阶微分方程组
  19. Visio图标下载链接
  20. linux下添加新用户,并赋予root权限

热门文章

  1. 苹果电脑macbookpro安装yarn工具
  2. 超级实习生名企内推实习付费吗?与付费实习有何区别?
  3. 微信小程序输入账号密码点击按钮登录事件示例代码
  4. 数据库连接池为什么首选Druid
  5. html页面下拉条位置,iframe滚动条位置控制
  6. iframe隐藏滚动条
  7. 计算机组装策略摘要,计算机组装与维护策略.docx
  8. 矩阵论复习笔记-华中科技大学
  9. 使用Python自动发送邮件
  10. python语音合成实现原理_python腾讯语音合成实现过程解析