C++ 【学习备忘】


C++ — Doc 官网

C++自学备忘

一、C++基础

《C++面向对象程序设计》千处细节、万字总结

《C++面向对象程序设计》✍千处细节、万字总结(建议收藏)

1、指针函数与函数指针

在这里插入图片描述

2、类

1、五种构造函数

C++ 拷贝构造函数和赋值构造函数
(1)默认构造函数
(2)初始化构造函数
(3)复制(拷贝)构造函数
(4)转换构造函数
(5)赋值构造函数

2、封装

3、继承

1、public继承
2、protected
3、private继承
4、virtual继承
请点击–> C++ 虚继承(菱形继承)详解

普通函数的继承 是一种实现继承,派生类继承了基类函数,可以使用函数,继承的是函数的实现。
虚函数的继承 是一种接口继承,派生类继承的是基类虚函数的接口,目的是为了重写,达成多态,继承的是接口。所以如果不实现多态,不要把函数定义成虚函数。

4、多态

1、虚函数
(1)动态绑定

在C++语言中,动态绑定只作用于虚函数,并且需要通过指针或引用调用。动态绑定直到运行时才确定到底执行函数的哪个版本。在C++ 中,动态绑定的意思是在运行时根据引用或指针所绑定对象的实际类型来选择执行虚函数的某一个版本。
(2)override
描述:override保留字表示当前函数重写了基类的虚函数。
目的:1、在函数比较多的情况下可以提示读者某个函数重写了基类虚函数(表示这个虚函数是从基类继承,不是派生类自己定义的);2、强制编译器检查某个函数是否重写基类虚函数,如果没有则报错。
用法:在类的成员函数 参数列表后面 添加该关键字既可。

//例子:
class Basevirtual void f();
}class Derived : public Base {
void f() override; // 表示派生类重写基类虚函数f
void F() override;//错误:函数F没有重写基类任何虚函数
}

(3)纯虚函数:在类的内部声明虚函数时,在分号之前使用了=0.

2、多态性

请点击–> C++_多态详谈

3、C++关键字

请点击-> C++关键字 如下:

alignasdecltypeinlinesignedunion
alignofdefaultintsizeofunsigned
asmdeletelongstatic
C++中static的作用
using
auto
C++ auto用法及应用详解
domutable
可变数据成员
static_assertvirtual
booldynamic_castnamespacestatic_castvoid
breakelsenewstructvolatile
caseenumnoexceptswitchwchar_t
catchexplicit
explicit构造函数只能用于直接初始化。
只对一个实参的构造函数有效。
nullptrtemplatewhile
charexportoperatorthis
char16_texternprivatethread_local
char32_tfalseprotectedthrow
classfloatpublictrue
constforregistertry
constexpr–C++11 friendreinterpret_casttypedef
const_castgotoreturntypeid 【 查看数据类型,常用:typeid(data).name() 】override
continueifshorttypenameassert

请点击–> C++语言关键字static和volatile 的含义和作用
请点击–> C++中的auto、const auto&

union:由于union里面的东西共享内存,所以不能定义静态、引用类型的变量。由于在union里也不允许存放带有构造函数、析构函数和复制构造函数等的类的对象,但是可以存放对应的类对象指针。编译器无法保证类的构造函数和析构函数得到正确的调用,由此,就可能出现内存泄漏。所以,在C++中使用union时,尽量保持C语言中使用union的风格,尽量不要让union带有对象。

4、转义字符

作用:用于表示一些不能显示出来的ASCII字符
现阶段我们常用的转义字符有: \n , \\ , \t

转义字符含义ASCII码值(十进制)
\a报警(响铃)符007
\b退格(BS) ,将当前位置移到前一列008
\f进纸符,换页(FF),将当前位置移到下页开头,012
\n换行(LF) ,将当前位置移到下一行开头010
\r回车符(CR) ,将当前位置移到本行开头013
\t水平制表(HT) (跳到下一个TAB位置)009
\v垂直制表(VT)011
\\代表一个反斜线字符""092
\’代表一个单引号(撇号)字符039
\"代表一个双引号字符034
\?代表一个问号063
\0数字0000
\ddd8进制转义字符,d范围0~73位8进制
\xhh16进制转义字符,h范围09,af,A~F3位16进制

5、C++内置函数

(1)排序函数sort()
(2)随机函数rand()和srand()
(3)间隔函数setw()

6、I / O-输入输出

(1)cin

cin: istream类型对象

(2)cout

cout:写到标准输出的ostream对象;
cout经过缓冲后输出,默认情况下是显示器。这是一个被缓冲的输出,是标准输出,并且可以重新定向。

(3)cerr

输出到标准错误的ostream对象,常用于程序错误信息;
cerr不经过缓冲而直接输出,一般用于迅速输出出错信息,是标准错误,默认情况下被关联到标准输出流,但它不被缓冲,也就说错误消息可以直接发送到显示器,而无需等到缓冲区或者新的换行符时,才被显示。一般情况下不被重定向。

(4)clog

clog流也是标准错误流,作用和cerr一样,区别在于cerr不经过缓冲区,直接向显示器输出信息,而clog中的信息存放在缓冲区,缓冲区满或者遇到endl时才输出.

(5)输入文件结束符

对于指出文件结束,不同操作系统有不同的约定。在Windows系统中,输入文件结束符的方法敲Ctrl+Z,然后按Enter或Return键。在UNIX系统中,包括Mac OS X系统中,文件结束符输入是用Ctrl+D。

(6)定义在iostream中的操作符(*代表默认状态)

boolalpha将true和false输出为字符串
*noboolalpha将true和false输出为1, 0
showbase对整型值输出表示进制的前缀
*noshowbase不生成表示进制的前缀
*dec整型值显示为十进制
hex整型值显示为十六进制
oct整型值显示为八进制
flush刷新ostream缓冲区
…等等

(7)文件及文件夹复制
请点击–> C++实现文件夹复制

7、C++强制类型转换

请点击-> 四种强制类型转换 fromCSDN
请点击-> 四种强制类型转换 from博客园
请点击-> C++ void指针(void*)简介
(1)static_cast

1、static_cast作用和C语言风格强制转换的效果基本一样,由于没有运行时类型检查来保证转换的安全性,所以这类型的强制转换和C语言风格的强制转换都有安全隐患。
2、用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。注意:进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
3、用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性需要开发者来维护。
4、 static_cast不能转换掉原有类型的const、volatile、或者__unaligned属性。(前两种可以使用const_cast 来去除)
5、在c++ primer 中说道:c++ 的任何的隐式转换都是使用 static_cast 来实现。

/* 常规的使用方法 */
float f_pi=3.141592f
int   i_pi=static_cast<int>(f_pi); /// i_pi 的值为 3

(2)dynamic_cast
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换(cross cast)。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。dynamic_cast是唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。
(3)const_cast
用于修改类型的const或volatile属性。 该运算符用来修改类型的const(唯一有此能力的C+±style转型操作符)或volatile属性。除了const 或volatile修饰之外, new_type和expression的类型是一样的。
①常量指针被转化成非常量的指针,并且仍然指向原来的对象;
②常量引用被转换成非常量的引用,并且仍然指向原来的对象;
③const_cast一般用于修改指针。如const char *p形式。
const_cast<目标类型>(标识符):目标类型只能是指针或者引用
(4)reinterpret_cast
new_type必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)。reinterpret_cast意图执行低级转型,实际动作(及结果)可能取决于编辑器,这也就表示它不可移植。

8、C++ 运算符

运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C++ 内置了丰富的运算符,点击此链接(可点击)将逐一介绍算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符和其他运算符。

请点击–> C++ 自增、自减运算符的重载和性能分析

9、命名空间(namespace)

参考链接请点击->:[参考-1]

10、string字符串

—WARNING—

尽管C++ 支持C风格字符串,但在C++程序中最好还是不要使用它们。这是因为C风格字符串不仅使用起来不太方便,而且极易引发程序漏洞,是诸多安全问题的根本原因。
如果程序的某处需要一个C风格的字符串,无法直接用string对象来代替它。为了完成此功能,string专门提供了一个名为c_str 的成员函数。如果执行完c_str()函数后,程序想一直都能使用其返回的数组,最好将该数组重新拷贝一份。

10.1
(1)C++中string、char 、char[]、const char的转换(其中涉及C字符串)

(2)C++中的String的常用函数用法总结—(较全,首先看)

(3)C++ string的用法和例子—(较全,优先看)

10.2 请点击-> c++的atoi和stoi一些区别

10.3 请点击-> C++中把字符串和数字连接起来
请点击—> C+±std:stringstream【数据类型转换、多个字符串拼接、分割字符串】

C++中把字符串和数字连接起来
//纯C++风格
string s = "陈明东";
int a = 52;
double b = .1314;
ostringstream oss;
oss << s << a << b;
cout << oss.str() << endl;
//C++11新特性
int a = 520;
float b = 5.20;
string str = "dong";
string res = str + to_string(a);
cout << res << endl;
res = str + to_string(b);
res.resize(8);
cout << res << endl;

10.4 请点击-> string::size_type

在C++标准库类型 string ,在调用size函数求解string 对象时,返回值为size_type类型,一种类似于unsigned类型的int 数据。可以理解为一个与unsigned含义相同,且能足够大能存储任意string的类型。在C++ primer 中 提到 库类型一般定义了一些配套类型,通过配套类型,库类型就能与机器无关。我理解为 机器可以分为16位 32位64位等,如果利用int等内置类型,容易影响最后的结果,过大的数据可能丢失。

11、文件读写

请点击-> C++文件读写详解(ofstream,ifstream,fstream)

12、C++异常处理

请点击-> 异常处理(try、catch、throw)from菜鸟教程

请点击-> [c++try语句块和异常处理

noexcept异常说明

noexcept 有两种含义:(1)当跟在函数参数列表后面时它是异常说明符;(2)而当作为noexcept异常说明的bool实参出现时,它是一个运算符。

13、预处理器(部分可用于调试)

请点击-> 条件编译#ifdef的妙用详解(#define、#undef、#ifdef、#ifndef、#if、#elif、#else、#endif、defined)
请点击-> C++各个平台的宏定义
请点击-> #pragma once与#ifndef的区别

13.1 预处理指令

#pragma region是Visual C++中特有的预处理指令。它可以让你折叠特定的代码块,从而使界面更加清洁,便于编辑其他代码。折叠后的代码块不会影响编译。你也可以随时展开代码块以进行编辑等操作。

int main()
{
...
#pragma region demo_region	//这里前面会有折叠符,折叠时提示 demo_region所写内容
int a = 10;
int b = 20;
int c = ADD( a + b ); 
#pragma endregion demo_region	//需要跟#pragma region配套使用
....
}

调试帮助
(1)assert预处理宏
(2)NDEBUG预处理变量
C++预编译器定义了5个对于程序调试很有用的名字

预处理宏👇:
1、_ _FILE_ _ :存放文件名的字符串字面值
2、_ _func_ _ :存放函数名的字符串字面值
3、_ _LINE_ _ :存放当前行号的整型字面值
4、_ _TIME_ _ :存放文件编译时间的字符串字面值
5、_ _DATE_ _ :存放文件编译日期的字符串字面值

14、多线程

14.1 请点击–> C++11 - thread多线程编程

14.2 请点击–> C++ thread用法总结(整理)

14.3 请点击–> 一文详解C++多线程

14.4 请点击–> C++多线程(一)thread类

joinable(): 判断是否可以成功使用join()或者detach(),返回true表示可以使用join()或者detach()
返回fasle表示不可以。
join()和detach()
join() 的作用是阻塞主线程,等待子线程完成。子线程结束后再来执行主线程
detach() 让子线程与主线程分开运行互不影响,主线程不会等待子线程结束。如果主线程先结束,子线程会被系统接管。这种做法是一种比较危险的做法,不建议使用。

15、线程锁

请点击–> C++11线程中的几种锁

C++ 11多线程与线程锁
std::thread线程。需引入头文件: #include <thread>
std::mutex互斥锁。需引入头文件: #include <mutex>
示例:std::mutex mtx;
mtx.lock();
mtx.unlock();
std::condition_variable定义条件变量(用来做线程间的同步通信),【条件变量需要和互斥锁一起使用】
需引入头文件: #include <condition_variable>
std::atomic <T>原子操作类, 需引入头文件: #include <atomic>
或:std::atomic_int mycount(100) ;
std::unique_lock < std::mutex>unique_lock是个类模板,工作中,一般lock_guard(推荐使用);lock_guard取代了mutex的lock()和unlock();unique_lock比lock_guard灵活很多,效率上差一点,内存占用多一点。
std::lock_guard<std::mutex>

16、不能被拷贝的类型,需要引用

例如std::thread, std::metux,std::ifstream, std::ofstream等类型

请点击–> C++中的不可复制类型

17、友元函数及友元类

友元函数是可以直接访问类的私有成员的非成员函数。
友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。
请点击–> C++友元函数和友元类用法详解

18、#include<>和#include“ ”的区别

一、引用的头文件不同
#include< >引用的是编译器的类库路径里面的头文件。
#include“ ”引用的是你程序目录的相对路径中的头文件。
二、用法不同
#include< >用来包含标准头文件(例如stdio.h或stdlib.h).
#include“ ”用来包含非标准头文件。
三、调用文件的顺序不同
#include< >编译程序会先到标准函数库中调用文件。
#include“ ”编译程序会先从当前目录中调用文件。
四、预处理程序的指示不同
#include< >指示预处理程序到预定义的缺省路径下寻找文件。
#include“ ”指示预处理程序先到当前目录下寻找文件,再到预定义的缺省路径下寻找文件。

19、模板编程

请点击–>C++之模板<template>

二、C++11新特性

1、C++左值和右值

值得一提的是,左值的英文简写为“lvalue”,右值的英文简写为“rvalue”。lvalue 是“loactor value”的缩写(左值引用符号:&),可意为存储在内存中、有明确存储地址(可寻址)的数据;而 rvalue 译为 “read value”(右值引用符号:&&),指的是那些可以提供数据值的数据(不一定可以寻址,例如存储于寄存器中的数据)。

通常情况下,判断某个表达式是左值还是右值,最常用的有以下 2 种方法。
(1)可位于赋值号(=)左侧的表达式就是左值;反之,只能位于赋值号右侧的表达式就是右值。举个例子:

int a = 5;

C++ 中的左值也可以当做右值使用,例如:

int b = 10; // b 是一个左值
a = b; // a、b 都是左值,只不过将 b 可以当做右值使用

(2)有名称的、可以获取到存储地址的表达式即为左值;反之则是右值。
以上面定义的变量 a、b 为例,a 和 b 是变量名,且通过 &a 和 &b 可以获得他们的存储地址,因此 a 和 b 都是左值;反之,字面量 5、10,它们既没有名称,也无法获取其存储地址(字面量通常存储在寄存器中,或者和代码存储在一起),因此 5、10 都是右值。(注意,以上 2 种判定方法只适用于大部分场景。)
(3)右值和左值引用成员函数
我们指出this的左值/右值属性的方式与定义const成员函数相同,即,在参数列表后放置一个引用限定符:

class Foo
{
public:
    Foo &operator=(const Foo&) &; //只能向可修改的左值赋值
    //Foo的其他参数
};
Foo &Foo::operator=(const Foo &rhs) &
{
    //执行将rhs赋予本对象所需的工作
    return *this;
}

引用限定符可以是&或&&,分别指出this可以指向一个左值或右值。类似const限定符,引用限定符只能用于(非static)成员函数,且必须同时出现在函数的声明和定义中。
对于&限定的函数,我们只能将它用于左值;对于&&限定的函数,只能用于右值:

Foo &retFoo();  //返回一个引用;retFoo调用是一个左值
Foo retVal();   //返回一个值;retVal调用是一个右值
Foo i, j;       //i和j是左值
i = j;          //正确:i是左值
retFoo() = j;   //正确:i是左值
retVal() = j;   //错误:retVal()返回一个右值
i = retVal();   //正确:我们可以将一个右值作为赋值操作的右侧运算对象
一个函数可以同时用const和引用限定。在此情况下,引用限定符必须跟随在const限定符之后:
class Foo{
public:
Foo someMem() & const;      //错误:const限定符必须在前
Foo anotherMem() const &;   //正确:const限定符在前
}

2、智能指针(smart pointer)

请点击–> auto_ptr 被弃用的原因
请点击–> 智能指针详解
请点击–> C++ STL 四种智能指针

在C++中,动态内存的管理是用一对运算符完成的:newdelete ,new: 在动态内存中为对象分配一块空间并返回一个指向该对象的指针,delete:指向一个动态独享的指针,销毁对象,并释放与之关联的内存(非必要,不建议使用,容易造成内存泄漏)。

2.1 shared_ptr(共享指针)

shared_ptr(共享指针)
参考链接请点击- -> [参考1]

共享指针两种初始化方式:

1、 使用原始指针创建 shared_ptr 对象
std::shared_ptr p1(new int());
上面这行代码在堆上创建了两块内存:
(1)存储int。
(2)用于引用计数的内存,管理附加此内存的 shared_ptr 对象的计数,最初计数将为1。
2、 创建空的 shared_ptr 对象
因为带有参数的 shared_ptr 构造函数是 explicit 类型的,所以不能像这样std::shared_ptr p1 = new int(); 隐式调用它构造函数。
创建新的shared_ptr对象的最佳方法是使用std :: make_shared:
std::shared_ptr p1 = std::make_shared();
std::make_shared 一次性为int对象和用于引用计数的数据都分配了内存,而new操作符只是为int分配了内存。

建议使用make_shared()< >创建 shared_ptr 对象,而不是使用默认构造函数创建。
std::shared_ptr<int> ptr_1 = std::make_shared<int>();
std::shared_ptr<int> ptr_2 (ptr_1);
 有两种方式可以将shared_ptr应用于标准容器(或者容器适配器等其他容器)。
 ()是将容器作为shared_ptr管理的对象,如shared_ptr<list<T> >,使容器可以被安全地共享,用法与普通shared_ptr没有区别,我们不再讨论。
 ()是将shared_ptr作为容器的元素,如vector<shared_ptr<T> >,因为shared_ptr支持拷贝语义和比较操作,符合标准容器对元素的要求,所以可以实现在容器中安全地容纳元素的指针而不是拷贝。

2.2 unique_ptr

unique_ptr

2.3 weak_ptr(弱指针)

weak_ptr(弱指针)
新进老大shared_ptr可以说近乎完美,但是通过引用计数实现的它,虽然解决了指针独占的问题,但也引来了引用成环的问题,这种问题靠它自己是没办法解决的,所以在C++11的时候将shared_ptr和weak_ptr一起引入了标准库,用来解决循环引用的问题。
请点击–> 【C++】weak_ptr弱引用智能指针详解

2.4 stl 智能指针和 boost 智能指针

请点击- -> stl智能指针和boost智能指针对比

3、=default的含义

默认构造函数的形式:Sales_data() = default;
明确一点:因为该构造函数不接受任何实参,所以它是一个默认构造函数。我们定义这个构造函数的目的仅仅是因为我们既需要其他形式的构造函数,也需要默认的构造函数。希望这个构造函数的作用完全等同于之前使用的合成默认构造函数。
在C++11新标准中,如果我们需要默认的行为,那么可以通过在参数列表后面写上**= default** 来要求编译器生成构造函数。其中,=default既可以和声明一起出现在类的内部,也可以作为定义出现在类的外部。和其他函数一样,如果=default在类的内部,则默认构造函数是内联的;如果它在类的外部,则该成员默认情况下不是内联的。

4、别名

类型别名
// UINT和Uint都是unsigned int的别名 //typedef: C语言中的
typedef unsigned int UINT;
using Uint = unsigned int;
using ULL = unsigned long long;

// using 定义别名模板,C++11新特性
template < typename T>
using vec = vector <T>;
namespace TestNamespace
{
	namespace OldNameSpace 
	{...}
	namespace OldN = OldNameSpace;
	inline namespace NewNameSpace
	{...}
};

// namespace可以直接命名空间别名
namespace TN = TestNamespace;

5、可变参数模版

一个可变参数
可变参数模版

6、标准库函数对象 & 可调用对象 & function

1 、表中所列的类型定义在functional头文件中

算术关系逻辑
plus<类型>equal_to <类型>logical_and <类型>
minus <类型>not_equal_to <类型>logical_or<类型>
multiplies <类型>greater <类型>logical_not <类型>
divides<类型>greater_equal <类型>
modulus <类型>less <类型>
negate <类型>less_equal <类型>
使用示例:
greater<string>()

2 、function是一个模板
function<类型> f ;
function<类型> f(nullptr);
function<类型> f(obj);

使用示例:
functional<int (int, int)>  f1 = divide();
lambda表达式赋值给一个函数,示例:
functional<int (int, int)>  f3 = [](int i, int j){return i * j;};

7、枚举与枚举类

请点击–> C++之enum枚举量声明、定义、使用与枚举类详解

8、C++11 return{}的含义

“返回用大括弧初始化的该函数对象(返回的类型和函数类型一样)” 举个例子后就能明白了
在C++11之前, 你想返回一个string的函数,你可能会这样写:

string get_string() {
    return string();
}

在C++11之后,可以这样写:

std::string get_string() {
    return {};   // 即返回这个函数所构造出来的对象
}

这里再举个例子:
vector<int> twoSum(vector<int>& nums, int target) {
	//...经过一系列操作后构造好了nums这个vector数组
	if(target > 10) return {};       //返回一个空的vector<int>对象
	else if(target < 5) return nums;    //直接返回nums作为对象
	else return {1, 2, 3};    //直接构造好vector<int>并将这个对象返回
}

9、C++标准库的更新

9.1 C++11 容器的非成员函数swap
早期标准库版本只提供成员函数版本的swap。非成员版本的swap在泛型编程中是非常重要的,统一使用非成员版本的swap是个好习惯。

a.swap(b);//成员版本
swap(a,b)//非成员版本

9.2 C++11 Lambda表达式
lambda表达式(也称为lambda函数)是在调用或作为函数参数传递的位置处定义匿名函数对象的便捷方法。

lambda 语法定义:
[capture](parameters) mutable ->return-type{statement}
///
1.[capture]:捕捉列表。捕捉列表总是出现在Lambda函数的开始处。
实际上,[]是Lambda引出符。
编译器根据该引出符判断接下来的代码是否是Lambda函数。
捕捉列表能够捕捉上下文中的变量以供Lambda函数使用;

2.(parameters):参数列表。
与普通函数的参数列表一致。
如果不需要参数传递,则可以连同括号“()”一起省略;

3.mutablemutable修饰符。
默认情况下,Lambda函数总是一个const函数,mutable可以取消其常量性。
在使用该修饰符时,参数列表不可省略(即使参数为空);

4.->return-type:返回类型。
用追踪返回类型形式声明函数的返回类型。
我们可以在不需要返回值的时候也可以连同符号”->”一起省略。
此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导;

5.{statement}:函数体。
内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。

请点击 --> C ++ Lambda表达式详解
请点击 --> 应用实例:c++ 排序后如何获取索引排列

9.3 C++11 无序关联容器

三、归类( 引入 )头文件

1、利用clock()测试函数运行时间

clock_t  startTime , endTime;
cout<<double(endTime - startTime) / CLOCKS_PER_SEC;

clock()是C/C++中计时函数,函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数 ,CLOCKS_PER_SEC表示一秒钟内CPU运行的时钟周期数(时钟计时单元)。
头文件:#include<>

2、获取当前系统时间

2.1
请点击–> 获取当前系统时间(time_t和tm)清晰梳理
包含头文件:#include <time.h>
2.2
time_t rawtime;
time(&rawtime);
data_node[“time”] = asctime(localtime(&rawtime)); //并将时间

3、遍历目录文件夹(获取文件列表)

请点击–> Linux C 读取文件夹下所有文件(包括子文件夹)的文件名

请点击–> Linux下 C++遍历目录下所有文件

请点击–> Linux C++读取目录下各文件内容

请点击–> Windows C++遍历文件夹指定扩展名

4、头文件iomanip

简介:是I/O流控制头文件,就像C里面的格式化输出一样。
请点击–>C++ 标准库之iomanip

定义在iomanip中的操作符

setfill(ch)用ch填充空白
setprecision(n)将浮点精度设置为n
setw(w)读或写值的宽度为w个字符
setbase(b)将整数输出为b进制

5、sleep函数(延迟函数)

//linux
#include <iostream>
#include <unistd.h>
using namespace std;          
int main()
{
    cout << "hello" << endl;
    sleep(1); //sleep() 秒级
    usleep(100000); //usleep() 微秒级
}
//windows//Windows下包含头文件 #include <windows.h> ,然后使用Sleep()函数,参数为毫秒,
//注意Sleep()中的S是大写
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
	Sleep(2000); // 2000ms = 2s
	cout << "hello world!" << endl;
	return 0;
}

6、C++11时间库(测试函数运行时间)

C++11 std::chrono时间库
示例代码:

using namespace std;
chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
/*
code bala~bala
*/
chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>(t2-t1);
cout<<"solve time cost = "<<time_used.count()<<" seconds. "<<endl;

四、STL ( stl )

请点击–> STL ( stl )用法总结
在这里插入图片描述

1、std::bind函数(参数绑定)

bind函数看做一个通用的函数适配器,它接受一个可调用对象callable,生成一个新的可调用对象newCallable。它可以把原可调用对象callable的某些参数预先绑定到给定的变量中(也叫参数绑定),然后产生一个新的可调用对象newCallable

auto newCallable = bind(callable, arg_list);
//以下应注释
callable依据手册可以是:
Callable object(function object, pointer to function, reference to function, pointer to member function, 
or pointer to data member)that will be bound to some arguments.

请点击-> C++11中的std::bind

2、std::unique函数

unique函数属于STL中比较常用函数,它的功能是元素去重。即”删除”序列中所有相邻的重复元素(只保留一个)。此处的删除,并不是真的删除,而是指重复元素的位置被不重复的元素给占领了(详细情况,下面会讲)。由于它 ” 删除 ” 的是相邻的重复元素,所以在使用unique函数之前,一般都会将目标序列进行排序

(1)unique函数的函数原型如下:

ForwardIterator unique(
	ForwardIterator first,
	ForwardIterator last
);

ForwardIterator unique(
	ForwardIterator first,
	ForwardIterator last,
	BinaryPredicate pred
);

这种类型的unique函数是我们最常用的形式。其中这两个参数表示对容器中[it_1,it_2)范围的元素进行去重(注:区间是前闭后开,即不包含it_2所指的元素),返回值是一个迭代器,它指向的是去重后容器中不重复序列的最后一个元素的下一个元素

(2)去重原理:

unique函数的去重过程实际上就是不停的把后面不重复的元素移到前面来,也可以说是用不重复的元素占领重复元素的位置。

(3)函数常用搭配:

unique函数通常和erase函数一起使用,来达到删除重复元素的目的。(注:此处的删除是真正的删除,即从容器中去除重复的元素,容器的长度也发生了变换;而单纯的使用unique函数的话,容器的长度并没有发生变化,只是元素的位置发生了变化)

3、容器erase函数

原型如下:
(1)string& erase ( size_t pos = 0, size_t n = npos );
(2)iterator erase ( iterator position );
(3)iterator erase ( iterator first, iterator last );

4、容器添加元素

请点击–> emplace_back() 和 push_back 的区别
可以发现push_back()与emplace_back()在用法上没有区别,主要的区别在于底层实现的机制不同。 push_back()添加元素时,首先会创建这个元素,然后再将这个元素拷贝或移动到容器中(如果是拷贝的话,事后会自行销毁之前创建的这个元素);emplace_back()添加元素时,则是直接在尾部创建这个元素,省去了拷贝或移动元素的过程。emplace_back()在内存与运行效率方面都优于push_back()。内存方面emplace_bakc()是就地构造,不用拷贝一个再使用;在效率方面,由于省去了拷贝构造过程,执行效率更高。

5、std::pair 与 std::make_pair函数

请点击–> C++ std::pair 与 std::make_pair
请点击–> C++ pair的基本用法总结(整理)

//pair是一个很实用的”小玩意“,当想要将两个元素绑在一起作为一个合成元素,
//又不想因此定义结构体时,使用pair可以很方便地作为一个替代品。
//也就是说,pair实际上可以看作一个内部有两个元素地结构体,
//且这两个元素的类型是可以指定的。
struct pair {
    typename1 first;
    typename2 second;
};
**pair**的定义
//要使用pair,应先添加头文件#include <utility>,并在头文件下面加上"using namespace std"
//注意:由于map的内部实现中涉及pair,因此添加map头文件时会自动添加utility头文件
//此时如果需要使用pair,就不需要额外再添加utility头文件
//pair有两个参数,分别对应first和second的数据类型,它们可以是任意基本数据类型或容器
//定义
pair<typeName1, typeName2> name;
//定义参数为string和int类型的pair
pair<string, int> p;
//初始化
pair<string, int> p("haha", 5);

//临时构建一个pair,有两种方法
//<1> 将类型定义写在前面,后面用小括号内两个元素的方式
pair<string, int> ("haha", 5)

//<2> 使用自带的make_pair函数
make_pair("haha", 5)

6、容器(vector、list、deque)

6.1 vector

6.1.1 vector相关用法

请点击–> vector用法

6.1.2 vector清空元素

请点击–> C++ vector清空元素的三种方法

6.1.3 vector内存释放

由于vector的内存占用空间只增不减,比如你首先分配了10,000个字节,然后erase掉后面9,999个,留下一个有效元素,但是内存占用仍为10,000个。所有内存空间是在vector析构时候才能被系统回收。empty()用来检测容器是否为空的,clear()可以清空所有元素。但是即使clear(),vector所占用的内存空间依然如故,无法保证内存的回收。
如果需要空间动态缩小,可以考虑使用deque。如果非vector不可,可以用 swap() 来帮助你释放内存。具体方法如下:

vector<int> nums; 
nums.push_back(1);
nums.push_back(1);
nums.push_back(2);
nums.push_back(2); 
vector<int>().swap(nums); //或者nums.swap(vector<int> ())
6.1.4 vector扩容

1、vector的reserve() 和 resize()
reserve():
的作用是更改vector的容量(capacity),使vector至少可以容纳n个元素。如果n大于vector当前的容量,reserve会对vector进行扩容。其他情况下都不会重新分配vector的存储空间。reserve()表示容器预留空间,但不是真正的创建对象,需要通过insert()或push_back()等操作创建对象。
resize():
既分配了空间,也创建了对象。这里空间就是capacity,对象就是容器中的元素。

2、vector的capacity() 和 size()
capacity是容器可存储的最大总数,size是当前容器存储的个数。
在这里插入图片描述在这里插入图片描述

6.1.5 vector合并与拼接

C++中如何合并两个vector?

6.1.6 vector容器逆序遍历

C+±vector:vector容器逆序遍历【for (auto it = v.rbegin(); it != v.rend(); it++){}】

6.2 list

6.3 deque

6.4 set

6.5 map

请点击–> C++三种容器:list、vector和deque的区别

摘自上方链接🔗
1、vector
连续存储结构,每个元素在内存上是连续的;支持 高效的随机访问和在尾端插入/删除操作,但其他位置的插入/删除操作效率低下; 相当于一个数组,但是与数组的区别为:内存空间的扩展。
2、deque ——双向开口的数据结构
连续存储结构,即其每个元素在内存上也是连续的,类似于vector,不同之处在于, deque提供了两级数组结构, 第一级完全类似于vector,代表实际容器;另一级维护容器的首位地址。这样,deque除了具有vector的所有功能外, 还支持高效的首/尾端插入/删除操作。
3、list ——双向开口的数据结构
非连续存储结构,具有双链表结构,每个元素维护一对前向和后向指针,因此支持前向/后向遍历。 支持高效的随机插入/删除操作,但随机访问效率低下,且由于需要额外维护指针 ,开销也比较大。

8、各种STL泛型算法汇总

请点击-> STL算法概观

函数算法名称解释说明
1. min_element()
2. max_element()
3. minmax_element()
1. 返回最小值元素
2. 返回最大值元素
3. 返回最小值和最大值元素
全排列函数:
1、std::prev_permutation()
2、std::next_permutation()
1、降序全排列
2、升序全排列(from官网)
std::getline()getline从输入流中读取字符, 并把它们转换成字符串。
std::pair()
std::make_tuple()std::make_tuple(type, type)
std::tuple()std::tuple的一个常见用途是从一个函数返回多个值。C++ - 函数返回多个返回值的方法总结解释: 是一个元组,可包含无限多不同类型变量,pair的升级版,但没有pair得成员变量first、second。
std::tie()解释:可以用于解包tuple元素;其构造函数返回一个元组。from-C++官网
std::hypot()hypot函数头文件math.h或cmath,hypot(a,b)的返回值为double类型,相当于sqrt(a**a+b*b)
std::replace()示例:std::replace (myvector.begin(), myvector.end(), 20, 99); from-C++官网
std::placeholdersC++11的占位符
std::condition_variable<condition_variable>是C++标准程序库中的一个头文件,定义了C++11标准中的一些用于并发编程时(多线程)表示条件变量的类与方法等。 条件变量是并发程序设计中的一种控制结构。
std::mutexC++11中新增了,它是C++标准程序库中的一个头文件,定义了C++11标准中的一些互斥访问的类与方法等。其中std::mutex就是lock、unlock。std::lock_guard与std::mutex配合使用,把锁放到lock_guard中时,mutex自动上锁,lock_guard析构时,同时把mutex解锁。mutex又称互斥量。
std::move()std::move理解 &&&&& std::move–from官网
std::function()std::function详解 ,std::function是一个函数包装模板,可以包装下列这几种可调用元素类型:函数、函数指针、类成员函数指针或任意类型的函数对象(例如定义了operator()操作并拥有函数闭包)。
需引入头文件:#include <functional
std::ref和std::crefstd::ref和std::cref使用,std::ref 用于包装按引用传递的值。std::cref 用于包装按const引用传递的值。
std::accumulate()求和函数,输入三个参数。
需引入头文件:#include < numeric >
std::copy()
std::equal()
这些只接受一个单一迭代器来表示第二个序列的算法,都假定第二个序列至少与第一个序列一样长
std::stable_sort()使相同长度的单词(字符串)按字典序排列
std::forward()std::forward 有两个参数:T 与 u 。当T为左值引用类型时,u将被转换为T类型的左值,否则u将被转换为T类型右值。如此定义std::forward是为了在使用右值引用参数的函数模板中解决参数的完美转发问题。
std :: getline()getline从输入流中读取字符, 并把它们转换成字符串。input - 流中获取数据,str - 把数据转换成字符串,delim - 分隔符。示例: std::getline(input, str, ‘.’);
std::iota()iota函数对一个范围数据进行赋值
std::count()计数函数,统计容器中等于value元素的个数。用法:count(first,last,value); first是容器的首迭代器,last是容器的末迭代器,value是询问的元素
std::count_if()返回区间中满足指定条件的元素数目。count_if(first,last,value,comp); first为首迭代器,last为末迭代器,value为要查询的元素,comp为比较函数。
std::numeric_limits在C/C++11中,std::numeric_limits为模板类,在库编译平台提供基础算术类型的极值等属性信息,取代传统C语言,所采用的预处理常数。比较常用的使用是对于给定的基础类型用来判断在当前系统上的最大值、最小值。若使用此类,需包含< limits >头文件。
std::tgamma()伽玛函数,可用来求阶乘。如:求3的阶乘,std::tgamma(4)。
std::distance()用法:distance( InputIt first, InputIt last ) 。作用是:返回两个迭代器之间的距离,也可以理解为计算两个元素 first 和 last 之间的元素数。
std::transform()有两种形式,std::transform在指定的范围内应用于给定的操作,并将结果存储在指定的另一个范围内。

五、C++相关的库

1、boost库

请点击-> boost官方网站
请点击-> boost官方帮助文档

1.1、boost线程

1.1 请点击-> boost::thread的六种使用方法总结

1.2 请点击-> boost库中thread多线程详解1——thread入门与简介

1.2、类和函数列表说明 (表格)

类和函数名称类和函数说明
boost::thread_group线程组
boost::asio::io_serviceboost::asio提供了一个跨平台的异步编程IO模型库,io_service类在多线程编程模型中提供了任务队列和任务分发功能。io_service最常用的接口是:run, post, stop。
boost::bind( )boost::bind操作,能够绑定函数与参数,绑定后能够改变参数数量,并且还可以使用占位符。它可以绑定普通函数也可以绑定类成员函数。
需包含头文件:#include <boost/bind.hpp>
#include<boost/function.hpp>

2、Armadillo库

线性代数与科学计算的C++库

补充:
Bandicoot - C++ library for accelerated linear algebra on GPUs
ensmallen - fast library for non-linear numerical optimisation
mlpack - extensive library of machine learning algorithms
CARMA - bidirectional interface between Python and Armadillo

安装Armadillo 进行矩阵计算(Install Armadillo on Windows for Visual Studio)

六、C++ 疑问整理及解决

类的常量成员函数中const的作用或意义用来安全。一般获取数据或获取类成员变量使用
如何销毁一个类对象程序会默认调用析构函数,也可手动调用析构函数(自己定义一个成员函数)
深拷贝与浅拷贝深拷贝:两个变量分别指向两个内存空间(存放数据相同)。浅拷贝 :两个变量指向同一个内存空间(存放数据相同),一个变量的数据改变,另一个数据也改变
core dumped (含义就是:当进程发生异常时,会把当时的内存信息倾倒出来,形成core文件)
六招制敌,搞定core dump问题
1、有可能内存泄漏
error: invalid conversion from ‘void*‘ to ‘char*‘ [-fpermissive]gcc与g++编译结果不同产生的错误
C++ Visual Studio报错:error C2061 “xxx”:本地函数定义是非法的1、一般这种情况会伴随着该文件有乱码出现,需要将编码方式修改为utf-8。
2、或者检查大括号是否匹配,可能存在丢失大括号的问题。

X、零碎知识或问题(零碎)

1、字面义:nan:not a number:即无法得到一个数字;
ind:indeterminate:不确定的。总的来说,就是无法得到一个确定的数字。
请点击–> C++ std::isnan和std::isinf

2、请点击–> 几种压缩算法比较

3、请点击–> memset()函数及其作用

4、yaml-cpp

4.1 请点击-> yaml-cpp保存角点信息(代码)

   for (int i = 0; i < corners_x.size(); i++) 
   {
       vector<double> corner;
       corner.resize(2);
       corner[0] = corners_x[i];
       corner[1] = corners_y[i];
       yml_node[“corners”][i] = corner;
       yml_node[“corners”][i] .SetStyle(YAML::EmitterStyle::Flow);
   }

保存之后的效果如下所示:
yaml

4.2 请点击–> C++ 开发中利用yaml-cpp读写yaml配置文件

请点击–> windows系统下C++使用TinyXML读写XML文件

请点击–> c++读取xml文件
请点击–> Tinyxml一一利用tinyxml读取节点元素属性值
5、请点击-> C/C++ 中容易造成缓冲区溢出的函数

6、请点击-> C++ 命令行参数解析

7、请点击-> C++中基类的析构函数为什么要用virtual虚析构函数?简而言之,防止内存泄露

8、请点击-> 代码注释规范之Doxygen <------->基于Doxygen的C/C++注释原则

9、请点击–> C++使用的json库nlohmann

10、请点击–> 文件描述符和打开文件之间的关系,文件描述符与exec()

11、请点击-> fflush函数–的作用

就单拿输出到屏幕上来说,printf 这样的函数不是直接打印到屏幕上的,而是先放在一个缓冲区中(stdout)中。如果收到了一个换行符,就会把这个缓冲区的内容打印到屏幕上,并清空。而 fflush 的作用就是直接把缓冲区的内容打印到屏幕上,并清空缓冲区。不必等换行符。

12、请点击–> C语言中的getchar() 与 putchar() 详解

putchar (‘\b’):b是back的缩写,\b表示后退一格。就是光标位置向前移动一位。

请点击-> printf 和 sprintf 和 fprintf 三个函数相关说明

13、请点击–> C++调用ros节点启动launch文件
14、请点击–> C/C++程序编译过程详解
请点击–> C++的编译过程及原理
15、请点击 --> c++ 排序后如何获取索引排列 同python的np.argsort()函数。

XX、杂杂杂杂杂

1、如何提升程序效率?
(1)逻辑方面
(2)算法方面
(3)库选用
2、funny注释代码
(1)佛祖保佑永无BUG 神兽护体 代码注释(各种版本)
(2)个性注释,让你的代码飞起来
(3)有Bug?你的代码神兽选对了吗

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值