C++
文章平均质量分 82
记录 C++ 的知识要点。
code_peak
这个作者很懒,什么都没留下…
展开
-
C++异常处理
异常是指存在运行时的反常行为,这些行为超出了函数正常功能的范围。典型的异常包括:数组越界、除零、失去数据库连接、遇到意外的输入等。处理反常行为可能是设计所有系统最难的一部分。原创 2023-01-11 01:15:55 · 1188 阅读 · 1 评论 -
C语言变长参数函数原理
变长参数函数概念在很多日志 Log 函数的封装中,可以看到可变长参数函数。C99中,出现了函数可变长参数特性,例如:printf 就可以接受任意长度的参数列表。看一下 printf 函数的定义:int printf (const char* format, ...);可以看到可变长参数除了有一个 format 固定外,其他参数的个数和类型就是可变的,用三个点 ... 作为参数占位符,代表变长参数。固定参数和可选参数共同构成变长参数函数的参数列表。任何一个边长参数的函数都可以分为两部分:固定参数和原创 2021-10-30 17:30:12 · 2272 阅读 · 0 评论 -
gdb配置打印STL容器脚本pretty printer
使用 gdb 调试是 Linux 下 C/C++ 开发不可少的工具,但是对于大型项目,调试需要有更高的效率,虽然 gdb 原生支持配置文件中自定义打印函数,可以自行定制这些函数。网上也有一些针对 STL 标准容器的 .gdbinit 文件,该文件会定义string、vector、map、set、deque、priority_queue 等,可以参考这里。把该文件保存 为 .gdbinit, 放在用户目录下~/.gdbinit,当执行 gdb 调试时会自动加载 .gdbinit 初始文件。使用该配置文件时,转载 2021-10-30 16:28:23 · 3004 阅读 · 0 评论 -
深入实践C++11智能指针
智能指针概念C/C++ 语言最为人所诟病的特性之一就是存在内存泄露问题,因此后来的大多数语言都提供了内置内存分配与释放功能,有的甚至干脆对语言的使用者屏蔽了内存指针这一概念。这里不置贬褒,手动分配内存与手动释放内存有利也有弊,自动分配内存和自动释放内存亦如此,这是两种不同的设计哲学。有人认为,内存如此重要的东西怎么能放心交给用户去管理呢?而另外一些人则认为,内存如此重要的东西怎么能放心交给系统去管理呢?在 C/C++ 语言中,内存泄露的问题一直困扰着广大的开发者,因此各类库和工具的一直在努力尝试各种方法去原创 2021-08-15 23:19:50 · 9292 阅读 · 12 评论 -
C++11的Lambda函数
Lambad函数概念参考:《深入理解C++11:新特性解析与应用》C++11 中新增了 Lambda 匿名函数,其基本格式如下:[捕捉列表] (参数) mutable -> 返回值类型 {函数体}参数说明:[] 是 Lambda 的引出符,捕捉列表能够捕捉上下文中的变量,来供 Lambda 函数使用,变量捕捉规则如下:[var] 表示以值传递方式捕捉变量 var[=] 表示值传递捕捉所有父作用域变量[&var] 表示以引用传递方式捕捉变量 var[&] 表示引转载 2021-08-02 00:41:00 · 706 阅读 · 0 评论 -
STL萃取(Traits)机制
问题前述我们希望有一个类,并有一个成员方法 GetSum 可以完成数组元素的一系列运算。具体看如下代码:#include <iostream>using namespace std;//处理int类型class IntArray{public: IntArray() { a = new int[10]; for (int i = 0; i < 10; ++i) { a[i] = i +原创 2021-08-02 00:26:13 · 1054 阅读 · 0 评论 -
关于gcc的__builtin_expect分支预测优化
在阅读 sylar框架源代码上看到了使用 __builtin_expect 的宏定义,一时有所不解,于是查找了很多资料,对并其做整理。Linux 下的很多代码我们经常看到 likey() 和 unlikely() 这两个宏,通常这两个宏定义是如下这样的形式:#define likely(x) __builtin_expect(!!(x), 1)#define unlikely(x) __builtin_expect(!!(x), 0)可以看出这两个宏都是使用了函数 __builti原创 2021-07-20 23:53:47 · 610 阅读 · 1 评论 -
C++虚继承中的虚基类表
虚继承主要解决多重继承会在子类中存在多份拷贝的问题,这不仅浪费空间,而且存在二义性。在之前的 C++ 继承中已经说过虚继承基本概念,这里不再赘述。这篇文章主要探究虚继承的原理。文章中多处给出了类实例对象的内存布局,查看其内存布局时,使用 VS 工具 /d1 reportAllClassLayout 进行查看,关于这个工具的详细介绍,请点击这里。虚继承的实现原理虚继承的底层实现一般与编译器相关,一般会通过虚基类表指针和虚基类表实现,先看如下这个程序:#pragma pack(1)class A{原创 2021-07-19 02:07:01 · 2280 阅读 · 0 评论 -
C++多态中的虚函数表
C++中的虚函数表之前的 C++ 继承中已经说过多态基本概念,这里不再赘述。再下面多处给出了类实例对象的内存布局,查看内存的布局时,使用 VS 工具 /d1 reportAllClassLayout 进行查看,关于这个工具的详细介绍,请点击这里。虚函数表的原理解析C++ 虚函数表主要出现在多态情况下。这里我们先从单继承下说明其虚函数表的原理,后面再说多继承情况下的。每个有虚函数的类的实例对象都有一个虚函数表指针成员,该虚函数指针一般位于对象存储空间的起始位置(相较于对象存储空间的起始位置偏移量为 0原创 2021-07-18 21:19:59 · 1041 阅读 · 0 评论 -
使用VS查看类实例的内存布局
使用VS查看类实例的内存布局图因为 MSVC 下使用 /d1 reportAllClassLayout 开关可以很方便的查看内存布局图,可以查看虚表,内存占用大小等。其使用方法是:首先确保电脑安装了 VS,我安装的是 VS2019,在 Win10 的开始菜单中依次找到:Visual Studio Tools -> x64 Native Tools Command Prompt for VS 2019 -> 打开,会进入 CMD 界面,然后切换到你的代码目录,比如我的代码在 CppTest 目原创 2021-07-18 20:29:45 · 2573 阅读 · 0 评论 -
C++继承
继承C++ 继承的一般形式如下:class DeriveClassName : Inheritlabel BaseClassName{ //...};DeriveClassName:派生类的名称。Inheritlabel:继承权限(public、protected、private),基类成员在派生类中的可见性。BaseClassName:父类名称。子类继承父类时是全盘继承,父类所有的东西都继承给子类,除了父类的构造和析构不继承。如下程序:#include <iostream&g原创 2021-07-17 01:17:56 · 574 阅读 · 1 评论 -
解决Qt程序打包后无法运行并提示缺少库文件
编译程序以 Release 方式编译生成 exe 程序.exe 就在你源码的同目录 build-MicroChat-Desktop... 下,直接双击打开会提示缺少一些库。依赖库先新建一个文件夹,将这个 .exe 文件移动到这个文件夹中,首先使用对应的编译器的 Qt 命令行,一般在开始菜单的Qt文件夹下(例如:Qt5.12.4(MSVC 2017 64bit)),然后打开,输入 cd /d D:\HelloWorld(你的路径),使用 windeployqt 命令执行 windeployqt Hel原创 2021-07-17 00:12:19 · 5108 阅读 · 2 评论 -
C的随机数函数
rand 和 srand 函数在 C 语言中使用 rand 函数产生一个随机数函数。并在 stdlib.h 中定义 rand 产生的随机数最大是 RAND_MAX,在 4 个字节下,可以表示的最大正数范围是 2147483647(int 类型)。rand 函数的原型如下:#includ <stdlib.h>int rand (void)rand 函数在调用时,先查询是否调用过 srand 函数,因为使用 srand 函数可以设置种子,如果有那么它会自动调用 srand(seed) 一原创 2021-07-15 00:33:06 · 4750 阅读 · 0 评论 -
C++编译优化RVO&NRVO&复制省略
转载原文:https://www.cnblogs.com/kekec/p/11303391.html编译器优化技术现代编译器缺省会使用 RVO(return value optimization,返回值优化)、NRVO(named return value optimization、命名返回值优化)和复制省略(Copy elision)技术,来减少拷贝次数来提升代码的运行效率。注1:vc6、vs 没有提供编译选项来关闭该优化,无论是 debug 还是 release 都会进行 RVO 和复制省略优化转载 2021-07-15 00:33:22 · 313 阅读 · 0 评论 -
C的时间操作相关函数
UNIX 时间概念在 UNIX 系统中,将从 1970 年 1 月 1 日开始经过的秒数用一个整数存放,这种高效简洁的时间表示方法被称为 Unix 时间戳,向左和向右偏移都可以得到更早或者更后的时间。实际开发中,对日期和时间的操作非常多,基本无处不在。时间的概念:本地时间(locale time)本地时间是在纪元时间(UTC)时间上加上时区。格林威治时间(Greenwich Mean Time GMT)世界时是最早的时间标准。在1884年,国际上将 1s 确定为全年内每日平均长度的 1/原创 2021-07-15 00:32:39 · 1337 阅读 · 0 评论 -
C++11 tuple元组
tuple元组tuple是一个元组容器,可以用于函数返回多个值tuple的两种初始化方式:tuple<int, int> t1(1, 2);tuple<int, int> t2{1, 2};make_tuple用于生成tuple对象,和pair和make_pire类似:auto t3 = make_tuple(1, 2);tuple的成员数量没有限制访问成员使用一个get的标准库函数模板,为了指定一个显示模板,必须指定想要访问的第几个成员。tuple<st转载 2021-07-14 00:35:13 · 203 阅读 · 0 评论 -
C++11 function函数对象
C++函数种类C++中的函数种类很多:函数函数指针Lambda函数bind创建的对象仿函数(重载了函数调用运算符的类)但这些函数可能共享一种调用方式。调用形式指明了调用返回的类型以及传递给调用的实参类型。比如:int(int, int);使用functionstd::function是一个通用的多态函数包装器,可以调用普通函数、Lambda函数、仿函数、bind对象、类的成员函数和指向数据成员的指针,function定义在名为function.h头文件中。是一个模板,在创建functi转载 2021-07-14 00:33:51 · 493 阅读 · 0 评论 -
C++11 bind函数
参考:《C++ Primer 第五版》参数绑定如果一个函数只在一两个地方操作,使用Lambad很方便,如果在很多地方操作,编写多次相同的Lambda函数就很不方便,需要定义函数。但是,定义的函数又不能完全代替能捕捉局部变量的Lambda函数,所以就出现了bind函数。bind函数是C++11标准库的函数,需要添加头文件#include <functional.h>bind就是一个通用的函数适配器,它可以接受一个可调用函数,生成一个新的可调用对象来“适应”原函数的参数列表。std::转载 2021-07-14 00:30:46 · 222 阅读 · 0 评论 -
volatile关键字详解
说到volatile关键字,首先需要从编译器优化开始说起。1. 编译器优化我们知道内存的访问速度是比不上CPU的处理速度的,为了提高性能,一般可以做出以下面两方面优化:硬件方面:引入高速缓存Cache,加速对内存的访问。另外现代CPU指令执行不一定严格按照顺序执行,没有相关性的执行可以乱执行,以充分利用CPU的指令流水线,提高执行速度。软件级的优化:一种是由编写代码的程序员优化,另一种是由编译器进行优化。编译器优化方法有:将内存变量缓存到寄存器中。由于访问寄存器比访问内存快得多,编译器在存原创 2021-07-14 00:22:22 · 180 阅读 · 0 评论 -
C++11 std::thread线程库
翻译原文:https://thispointer.com/c11-tutorial/C++11 线程库介绍C++11 中新增了多线程 std::thread,相比之前使用较多的是操作系统提供的 POSIX 线程接口,新标准引入了线程库无疑带来了许多便利。要使用 C++11 多线程,首先 gcc 编译器版本需要大于4.8,并且编译时,需要加上参数 -std=c++11 -lpthread,可见,C++11 的线程是对 POSIX 线程的封装。C++11 线程创建在每个 C++ 应用程序中,都有一个默转载 2021-06-25 02:07:20 · 2305 阅读 · 1 评论 -
C++11 std::chrono时间库
参考:https://blog.csdn.net/oncealong/article/details/28599655https://blog.csdn.net/WizardtoH/article/details/81738682std::chrono 概念chrono是一个模版库,包含了一系列时间相关功能。可以很容易的实现定时功能。chrono库主要包含了三种类型:时间间隔 Duration、时钟 Clocks 和时间点 Time point。Duration(时间间隔)duration表示转载 2021-06-25 01:16:16 · 867 阅读 · 0 评论 -
std::forward完美转发
完美转发概念所谓完美转发,指的是在函数模板中,完全依照模板的参数类型,将参数传递给函数模板中调用的另外一个函数。比如:template <typename T>void IamForwording(T t) { IrunCodeActually(t); }上面的 IamForwording 是一个转发函数模板,而函数 IrunCodeActually 则是真正执行代码的目标函数。从函数 IrunCodeActually 的角度而言,总是希望转发函数将参数按照传入 Ia原创 2021-06-25 01:05:10 · 789 阅读 · 0 评论 -
std::move移动语义
std::move 概念参考:《深入理解C++11:新特性解析与应用》在 C++11 中,标准库在 <utility> 中提供了一个有用的函数 std::move,这个函数的名字具有迷惑性,实际上 std::move 并不能移动任何东西,唯一的功能就是将一个左值强制转换为一个右值引用,继而可以通过右值引用使用该值,以便用于移动语义。从实现上来看,std::move 基本等同于一个类型转换:static_cast<T&&>(lvalue);值得一提的是,被转原创 2021-06-25 00:56:12 · 900 阅读 · 0 评论 -
C++11右值引用
指针成员和拷贝构造函数参考:《深入理解C++11:新特性解析与应用》对于 C++ 程序员来说,如果类中包含了一个指针成员 p 的话,需要小心拷贝构造函数的编写,否则很容易出现严重内存错误。当使用编译器隐式生成的拷贝构造函数时,用一个对象 a 去构造另一个对象 b,只是把两个指针指向了同一块内存,当对象 a 作用域结束后会调用其析构函数,释放了空间,这时候对象 b 的成员 p 就成了一个“悬挂指针”,其不再指向有效的内存。当对象 b 作用域结束后,去调用析构函数,就会造成严重的内存错误。这个问题就是原创 2021-06-25 00:42:00 · 403 阅读 · 1 评论