C++ 概念总结(基于 C++11)

构造

  • 构造函数形式:

    • 默认构造函数
    • 拷贝构造函数
      • 定义: 当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数
      • 形式: A(const A& h){}
      • 调用时机:
        • 当对象作为参数传递时
    • 赋值操作符:
      • 定义: 赋值操作符可以通过制定不同类型的右操作数而重载。
      • 形式: A& operator = (const A& h){}
      • 调用时机:
        • 当对象需要用 ‘=’ 进行赋值时
    • 移动构造函数
      • 定义: 源对象资源的控制权全部交给目标对象
      • 形式: A(A && h){}
      • 调用时机: 使用临时对象进行赋值
    • 移动赋值操作符: 基本同上
  • C++11 中的是 构造函数被子类继承,并且是隐式的.
  • 委派构造: 委派构造函数将构造任务委派给目标构造函数
    • 委派构造函数不能带有初始化列表
  • C++ 中的 初始化形式更加多样
    • 等号 “=”
    • 等号加上花括号 int a = {3 + 4}
    • 圆括号表达式 int a(3+4)
    • 花括号初始化列表 int a{3+4}
      • 对于自定义类需要借助 initializer_list 构造函数

移动语义

  • C++ 中的值类型分为 左值,右值,将亡值(可以简单的看成将被右值引用的值)
  • 右值操作: std::move / std::forword
  • 引用折叠: (&.. 总能被折叠为正确的 & / &&)

POD 类型

POD (Plain Old Data)字面上理解,是原始的数据,其体现了与 C 的兼容性,其优势如下

  • 字节赋值,代码中我们可以安全地使用 memset/memcpy 对 POD 类型进行初始化和拷贝等操作
  • 提供对 C 内存布局兼容. C++ 程序可以与 C 函数进行互相操作,因为 POD 类型的数据在 C 与 C++ 间的操作总是安全的
  • 保证了静态初始化的安全有效.静态初始化在很多时候能搞提高程序的性能,而 POD 类型的对象初始化往往更加简单(比如放入目标文件的 .bss 段,在初始化中直接被赋 0).

满足 POD 类型的必须为 trival 或者 standard layout

  • trilvial

    • 构造函数/析构函数/复制构造/移动构造/复制赋值运算符 必须为默认
    • 不能包含虚拟函数和虚拟基类
  • standard layout
    • 所有非静态数据成员均符合标准布局类型,其基类也符合标准布局.
    • 所有非静态成员都有相同的访问权限
    • 没有虚拟函数和虚基类
    • 类中第一个非静态成员的类型与其基类不同 //因为 C++ 的标准中定义类型相同的对象必须地址不同!
    • 在class或者struct继承时, 满足以下两种情况之一
      • 派生类中有非静态成员, 且只有一个仅包含静态成员的基类.
      • 基类有非静态成员,派生类没有非静态成员.

        (换句话说,非静态成员不能同时存在于基类和派生类中咯?)

C++11 引入非受限联合体的支持

自定义字面量

内联名字空间

  • 可以在父作用域直接被查找
  • ADL: 可以通过对象的名字空间直接推到出来

using 的扩展

  • 可以取代 typedef
  • 更加灵活的用法 template using MapString = std::map

动态类型

  • auto
  • 可以通过 typeid 查询的类的相关信息
  • decltype 推到四规则(假设 e 是 T 类型)
    • 如果没有带括号的标记符表达式或者类成员访问表达式,则返回推到类型 T = decltype(e) //表达式
    • 否则,如果 e 是一个将亡值,那么返回 T&&
    • 否则,如果 e 是一个左值,则返回 T&
    • 否则,decltype(e) 的推到值为 T //对象 e

C++11引入枚举类: enum class Type{}

智能指针

智能指针实际上是一个栈对象,并非指针类型,在栈对象生命期即将结束时,智能指针通过析构函数释放有它管理的堆内存

  • std::auto_ptr 管理从 new 形式获取的对象,在 auto_ptr 销毁的时候会释放这个对象.复制这个指针对象会导致它持有的对象移交所有权.
  • std::scoped_ptr 独享所有权,不可复制
  • std::shared_ptr 自带引用计数,看似完美
  • std::scoped_array 数组指针,也是禁用拷贝复制的
  • std::shared_array 数组指针,不再禁用拷贝复制
  • std::weak_ptr 引用,但不计数
  • std::intrusive_ptr 插入智能指针,需要手动增加计数

类型转换

  • 隐式转换

    • 算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型。
    • 一种类型表达式赋值给另一种类型的对象: 目标类型是被赋值对象的类型(void指针赋值给其他指定类型指针时,不存在标准转换,编译出错)
    • 将一个表达式作为实参传递给函数调用,此时形参和实参类型不一致:目标转换类型为形参的类型
    • 从一个函数返回一个表达式,表达式类型与返回类型不一致:目标转换类型为函数的返回类型
  • 显式类型转换
    • static_cast < type-id > ( expression )

      • 基本类型转换,但没有运行时类型检查来保证转换的安全性。
      • static_cast不能转换掉 const , volitale , __unaligned属性。
    • dynamic_cast < type-id > ( expression )
      • 说明: Type-id必须是类的指针,类的引用或者void *;type-id / expression 必须同为指针或者引用。
      • dynamic_cast具有类型检查的功能
    • reinpreter_cast (expression)
      • 关键字 re-inpreter 重解释! 不通类型之间的互转
    • const_cast (expression)
      • 去常量性

lambda 表达式

[ capture ] ( params ) mutable exception attribute -> ret { body }

  • [] 不截取任何变量
  • [&} 截取外部作用域中所有变量,并作为引用在函数体中使用
  • [=] 截取外部作用域中所有变量,并拷贝一份在函数体中使用
  • [=, &foo] 截取外部作用域中所有变量,并拷贝一份在函数体中使用,但是对foo变量使用引用
  • [bar] 截取bar变量并且拷贝一份在函数体重使用,同时不截取其他变量
  • [x, &y] x按值传递,y按引用传递
  • [this] 截取当前类中的this指针。如果已经使用了&或者=就默认添加此选项。

常量表达式 constexpr

  • 常量表达式函数:

    • 函数体只有单一的 return
    • 必须有返回值
    • 使用前必须定义
    • 返回语句表达式中不能使用非常量表达式的函数,全局数据,且必须是一个常量表达式
  • 自定义类型常量,需要添加常量构造函数 constexpr T(){}
  • C++11 支持变长模板 //代表 => tuple
  • constexpr 为编译时确定

原子操作模板: std::atomic

对齐支持: alignof / alignas

quick_exit/at_quick_exit

时间: 2024-10-10 07:38:21

C++ 概念总结(基于 C++11)的相关文章

基于C++11的线程池

1.封装的线程对象 class task : public std::tr1::enable_shared_from_this<task> { public: task():exit_(false){} task( const task & ) = delete; ~task(){} task & operator =( const task &) = delete; void start(); void stop() { exit_ = true; sync_.not

第一次作业:基于Linux0.11操作系统的进程模型分析

1.前言 本文基于Linux0.11操作系统的源代码,分析其进程模型. Linux0.11下载地址:https://zhidao.baidu.com/share/20396e17045cc4ce24058aa43a81bf7b.html 2.进程的定义 程序是一个可执行的文件,而进程(process)是一个执行中的程序实例. 进程和程序的区别: 几个进程可以并发的执行一个程序 一个进程可以顺序的执行几个程序 进程由可执行的指令代码.数据和堆栈区组成.进程中的代码和数据部分分别对应一个执行文件中的

基于c++11新标准开发一个支持多线程高并发的网络库

背景 新的c++11标准出后,c++语法得到了很多的扩展,比起以往任何时候都要灵活和高效,提高了程序编码的效率,为软件开发人员节省了不少的时间. 之前我也写过基于ACE的网络服务器框架,但ACE毕竟有些臃肿,内部对象关系错综复杂,容易给人造成只见树木不见森林的错觉. 所以打算用c++11开发一个较为简洁,高效,支持高并发的网络库. 开源         花了两三周,终于把基础的结构开发完成,代码也开源在github上,网址是 https://github.com/lichuan/fly 欢迎各位

基于C++11的call wrapper

要在C++中应用AOP,不像在其他的基于解释器的语言中那么方便,作为一种静态语言,如果给函数或者类的方法造一个wrapper,在wrapper里面嵌入调用前的代码和调用后的代码,也能达到一定程度的代码织入的效果.在C++11之前,要给一个函数或者方法做个能返回调用结果的wrapper并不简单,会比较复杂,而在C++11里面可以使用function模版,以及函数返回类型的推定,通过生成一个内嵌类的对象的构造函数来执行before动作,析构函数来实现after动作,而具体的before和action

基于C++11的线程池,简洁且可以带任意多的参数

咳咳.C++11 加入了线程库,从此告别了标准库不支持并发的历史.然而 c++ 对于多线程的支持还是比较低级,稍微高级一点的用法都需要自己去实现,譬如线程池.信号量等.线程池(thread pool)这个东西,在面试上多次被问到,一般的回答都是:"管理一个任务队列,一个线程队列,然后每次取一个任务分配给一个线程去做,循环往复." 貌似没有问题吧.但是写起程序来的时候就出问题了. 废话不多说,先上实现,然后再啰嗦.(dont talk, show me ur code !) 代码实现 1

C++构造函数的几个难点(基于C++ 11)

快要有一个月没有更新博客了,是时候再动一动笔啦!因为最近在学习C++,在学习过程中看了好多书,也在实际训练中遇到了一些问题.所以在接下来的时间里,应该会对C++里自己遇到的一些难点写几篇专题,就当是为自己梳理巩固知识啦! 我们都知道所谓构造函数就是类用来初始化各个数据成员的(非静态),如果成员都没初始化好,那么在对类的后续操作中肯定会遇到各种莫名其妙的错误.所以,我们有必要对构造函数做一个全面的了解,知道在各种情况下,构造函数都是怎样执行的,这样才能对类进行完美的控制. 默认构造函数: clas

一个基于C++11的单例模板类

1 #ifndef _SINGLETON_H_ 2 #define _SINGLETON_H_ 3 4 #include <mutex> 5 #include <memory> 6 7 template<typename T> 8 class Singleton { 9 public: 10 template <typename... ArgTypes> 11 static T* getInstance(ArgTypes... args) { 12 stat

基于vue-cli3.11.0创建创建vue项目

如果电脑已安装vue-cli2.9.6,需要先卸载,然后重装vue-cli3.11.0操作如下 等待几分钟,卸载完成,输入npm install -g @vue/cli 等待安装完成,输入vue -V查看脚手架版本号 下面开始创建项目 首先进入你指定的工作空间文件夹,输入vue create 项目名称 选择default,等待项目创建完成,输入cd 项目名称,进入项目,然后启动项目npm run serve 启动成功后,可通过url在浏览器中打开项目查看 浏览器打开: 原文地址:https://

基于C++11线程池

1.包装线程对象 class task : public std::tr1::enable_shared_from_this<task> { public: task():exit_(false){} task( const task & ) = delete; ~task(){} task & operator =( const task &) = delete; void start(); void stop() { exit_ = true; sync_.noti