CPP_HelloWorld 1 2 3 4 5 6 7 8 #include <print>  int  main (int  argc, char * argv[])  {	std::println ("hello world" ); 	return  0 ; } 
 
1 2 3 4 5 6 7 8 #include <iostream>  int  main (int  argc, char * argv[])  {	std::cout << "hello world"  << std::endl; 	return  0 ; } 
 
命名空间 用来解决include两个库,但是两个库有同名同参同返回值的函数的冲突。只要使用namespace::function来调用就可以避免冲突,相当于给函数加了前缀。
using namespace xxx 1 2 3 4 5 6 7 8 #include <print>  int  main (int  argc, char * argv[])  {	using  namespace  std; 	println ("hello world" ); 	return  0 ; } 
 
使用using namespace std,使得该块剩下部分的函数如果找不到就优先指定为std中的函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <print>  void  println (const  char * p)  {	; } int  main (int  argc, char * argv[])  {	using  namespace  std; 	println ("hello world" ); 	return  0 ; } 
 
该情况下优先调用自己的println
using x::y 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <print>  void  println (const  char * p)  {	; } int  main (int  argc, char * argv[])  {	using  std::println; 	println ("hello world" ); 	return  0 ; } 
 
使得之后块的y函数始终加x命名空间,此时println为std
上面两种同时使用时,using效果大于using namespace,两个都是using namespace时,需要转换规则。两个都是using时,using效果只针对到下一个using为止。using namespace不可以同时在全局使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <print>  namespace  b{ 	void  println (const  char * p)  	 {		; 	} } int  main (int  argc, char * argv[])  {	using  std::println; 	println ("hello world" ); 	using  b::println; 	println ("hello world" ); 	return  0 ; } 
 
1 2 3 4 5 6 7 8 9 10 重载解析(Overload Resolution)决胜法则 即使 b::println 与 std::println 同时可见,编译器会根据下面原则选最优匹配: 普通函数优先:非模板函数优于函数模板 参数匹配度:精确匹配(const  char * → const  char *)优于模板推导或额外转换 在 C++23  <print> 中,std::println 通常是一个可变参函数模板,需要做模板推导;而 b::println (const  char *) 则是完全精确匹配的普通函数。 结果:两次调用都选中了 b::println。 
 
面向过程中和C不一样的部分 基本变量 添加bool类型:true和false
添加auto类型,自动识别变量类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <print>  bool  isZero (int  d)  {	return  d == 0 ; } int  main (int  argc, char * argv[])  {	auto  d = 0 ; 	if  (isZero (d) == true ) 		std::println ("it is zero!" ); 	return  0 ; } 
 
foreach 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 std::vector<int > v{1 ,2 ,3 ,4 ,5 }; for  (const  auto & x : v) {    std::cout << x << ' ' ; } std::map<std::string,int > m {     {"apple" ,  3 },     {"banana" , 5 },     {"cherry" , 2 } }; for  (const  auto & [key, value] : m) {    std::cout << key << " -> "  << value << "\n" ; } int  a[2 ][3 ] = {{1 ,2 ,3 },{4 ,5 ,6 }};for  (auto & row : a) {    for  (auto  x : row) {         std::cout << x << ' ' ;     }     std::cout << '\n' ; } 
 
用于快速遍历容器
基本内存分配 new和delete关键字用于分配动态内存
1 2 3 4 5 6 7 int * a = new  int (3 );int * b = new  char (4 );int * c = new  int [10 ];delete  a;delete  b;delete [] c;
 
oprator new和oprator delete是函数,用于进行重载
额外指针类型与类型转换 空指针类型为std::nullptr_t。可以和任意类型非函数/类指针隐式转换。 于此对应的,void*不再自动隐式转换 同时定义了std::ptrdiff_t/std::intptr_t / std::uintptr_t来存放指针和差值,可以直接和值类型转换
1 2 3 int * a = new  int (3 );int * b = new  int (4 );std::ptrdiff_t  diff = a - b; 
 
const,auto,ptr,refer 最痛苦的一集。
const表示变量不可修改。 auto表示自动推断声明的变量类型。 *表示声明指针
引用 &表示声明引用。引用是变量的别名,比如:
1 2 3 4 int  a = 1 ;int &b = a;b++; cout<<a; 
 
左值引用是只能指向一个变量的指针。即: int *const b = a;
eg:
1 2 3 4 5 6 7 8 9 10 11 12 void  foo (int & a,int & b)  {    a = a+b;     b = a-b;     a = a-b; } int  main (void )  {    int  a=0 ;     int  b=1 ;     foo (a,b);     foo (1 ,2 ); } 
 
常量引用是带const的左值引用,不能用它来变更值。
eg:
1 2 3 4 5 6 7 8 9 void  foo (const  string& a)  {    cout<<a; } int  main (void )  {    string a ("hello" )  ;     foo (a);     foo ("world" ); } 
 
右值引用只能绑定一个右值:int&& x = 1;。也许是为了让函数可以传引用,又可以直接传值
eg:移动
1 2 std::string make_str ()   { return  "temp" ; }std::string s = std::move (make_str ()); 
 
顶层底层const  
const char为底层const *const为顶层const
auto 1 2 3 int  a =1 ;int &b =a;auto  c = b;
 
忽略引用,需要时,显式声明
1 2 3 4 5 6 7 int  a = 0 ;const  int  b = a,&c=b;auto  k = b;auto  l = c;auto  m = &a;auto  n = &b;auto  o = &c;
 
忽略顶层const,需要时,显式声明
1 2 const  int  a = 0 ;auto & b = a;
 
如果auto有&,保持顶层const
如果原值为数组,推导指针,如果原值为数组&推导数组。
后置类型推导也会用auto推导函数返回值
1 2 3 4 template <typename  T, typename  U>auto  add (T t, U u)  -> decltype (t + u)   {    return  t + u; } 
 
类型转换 C风格:(char)a CPP风格:char(a)
上面为隐式转换,会依次尝试下面几种显式找到合适的转换方式:
运算符 
值 
指针 
对象 
 
 
static_cast<T>(expr) 
支持的隐式转换 
void*到T*的转换,首先得是可相互转换的(包括指向类的指针和指向该类第一个非静态成员的指针) 
用户定义转(父类到子类等) 
 
const_cast<T>(expr) 
移除表达式的const或增加表达式的volatile修饰,不能修改底层const 
同左,函数指针不受影响 
同左,成员函数指针不受影响 
 
dynamic_cast<T>(expr) 
无 
沿继承结构向上/下/横向将指针/引用转换为类,可能需要运行时检查 
无 
 
reinterpret_cast<T>(expr) 
自由转换,没有限制 
自由转换,没有限制 
自由转换,没有限制 
 
异常处理 1 2 3 4 5 6 7 8 9 10 try {    throw  expr; }catch (T e1){      }catch (T e2){      }catch (...){      } 
 
面向对象部分 类声明 1 2 3 4 5 6 class  myclass {    int  a;		     float  b; public :    void  change (void )  ; }; 
 
1 2 3 4 5 6 7 8 9 myclass::myclass (){int  k = 0 ,float  e = 0.0 }{     a = k;     b = e; } myclass tt = myclass (1 ,1.0 ); myclass tt (1 ,1.0 )  ;myclass tt; myclass::~myclass (){} 
 
如果构造函数支持一个参数,支持直接赋值:
classname object = value;
this指针 如果方法涉及到两个或以上的对象,则需要使用this指针。this指针指向调用这个方法的对象的地址
内部的缩写
a等价于this->a
要引用整个表达对象(对象的值)时,用*this,
多态 继承 1 2 3 4 5 6 7 8 9 10 class  Person  {public :    std::string name;     int  age; }; class  Student  : public  Person {public :    std::string studentID; }; 
 
public表示共有还是共有,保护还是保护 protected表示共有变为保护,保护还是保护 private 共有/保护变为私有
多继承 1 2 3 4 5 6 7 class  Printer  {  };class  Scanner  {  };class  MultiFunctionDevice   : public  Printer,     public  Scanner {  }; 
 
虚继承 1 2 3 4 class  A  {  };class  B  : virtual  public  A {  };class  C  : virtual  public  A {  };class  D  : public  B, public  C {  };
 
虚函数 virtual声明关键字
1 2 3 4 5 class  Base  {public :    virtual  void  foo1 (int )  ;     virtual  void  foo2 (int )  ; }; 
 
1 2 3 4 5 6 7 8 class  Derived  : public  Base {public :         void  foo1 (int )  override  ;                     void  foo2 (int )  const  final  ;           }; 
 
如果含=0表示纯虚函数,必须在某个派生类提供定义,含有纯虚函数的类不能实例化,派生函数同理。
1 2 3 4 5 class  Abstract  {public :    virtual  void  func ()   = 0 ;        virtual  ~Abstract () = default ; }; 
 
运算符重载 运算符重载是一种多态。C++根据操作数的数目和类型来决定采用哪种操作。
格式:
1 2 3 4 5 6 7 8 9 10 11 12 myclass operator +(const  myclass& t) const ; myclass myclass::operator +(const  myclass & t) const {     myclass k;     ...     return  k; } a = b.operator +(c); a = b + c; 
 
重载的限制 
重载后的运算符必须至少有一个操作数是用户定义的类型。 
使用运算符时不能违反运算符原来的语法规则。(操作数相等,不能修改操作优先级) 
不能创建新的运算符 
不能重载
sizeof:sizeof运算符 
.:成员运算符 
.*:成员指针运算符 
:::作用域解析运算符 
?::条件运算符 
typeeid:一个RTTI运算符 
const_cast:强制类型转换运算符 
dynamic_cast:强制类型转换运算符 
reterpret_cast:强制类型转换运算符 
stati_cast:强制类型转换运算符 
 
 
只能通过成员函数重载的运算符
=:赋值运算符 
():函数调用运算符 
[]:下标运算符 
->:通过指针访问类成员的运算符 
 
 
 
lambda表达式和函数式编程 在面向对象中用表达式声明和定义一个函数,使其可以捕获上层函数的变量,实现闭包。或是定义只能在某个函数中使用的匿名函数
语法 1 [capture list] (parameter list) [mutable/exception /attribute] -> return  type  {  function  body  } 
 
capture list:捕获列表
值捕获,定义时直接传值 
引用捕获,内部使用的是对应变量的引用 
隐式捕获,捕获所有外部变量,=表示值捕获,&表示引用捕获 
初始化捕获,捕获列表中可以定义变量,且可以自动auto 
 
 
parameter list:传入参数列表,同普通的函数 
[mutable/exception/attribute]:不加mutable会自动给按值捕获的变量加const 
type:返回类型,省略后自动推导 
function body:函数体 
 
举例 自定义排序算法
1 sort (arr,[](int  a,int  b){return  a>b;});
 
auto泛型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int  main (void )  {    auto  f = [] (auto  x) -> auto      {         if  (is_integral<decltype (x)>::value)         {             return  x * 2 ;         }         else  if  (is_floating_point<decltype (x)>::value)         {             return  x / 2 ;         }         else          {             return  x;         }     }; } 
 
捕获类中的成员
1 2 3 4 5 6 class  A {    int  num;     void  test ()  {         auto  func = [*this ](){return  2 *num;};     } } 
 
智能指针 自动管理内存的指针,不需要手动释放
1 2 3 4 5 6 7 8 #include  <memory>  void  demo ()   {    std::unique_ptr<int > p1 = std::make_unique <int >(42 );     *p1 = 100 ;     auto  p2 = std::move (p1); } 
 
unique指针不能复制,只能移动
1 2 3 4 5 6 7 8 9 10 11 12 #include  <memory>  #include  <iostream>  void  demo ()   {    auto  p1 = std::make_shared <int >(55 );     std::cout << p1.use_count ();     {         auto  p2 = p1;         std::cout << p1.use_count ();     } } 
 
shared指针自动计数并删除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include  <memory>  #include  <iostream>  void  observe (std::weak_ptr<int > wp)   {    if  (auto  sp = wp.lock ()) {                 std::cout << *sp;     } else  {         std::cout << "expired" ;     } } int  main ()   {    std::weak_ptr<int > wp;     {         auto  sp = std::make_shared <int >(10 );         wp = sp;         observe (wp);       }     observe (wp);       } 
 
weak指针,关联一个shared_ptr
移动语义与完美转发 move的函数定义:
1 2 3 4 template  <class  _Ty >remove_reference_t <_Ty>&& move (_Ty&& _Arg)   {    return  static_cast <remove_reference_t <_Ty>&&>(_Arg); } 
 
遵循折叠规则:
组合形式 
折叠后结果 
 
 
&  与 & 
& 
 
&  与 && 
& 
 
&& 与 & 
& 
 
&& 与 && 
&& 
 
泛型与模板 1 2 3 4 template  <class  T1 >auto  move (T1 x,int  y)   {    return  x+y; } 
 
自动编译成多个函数,只要使用了不同的类型就有一个
std库 C++ 标准库 | 菜鸟教程