首页 > 编程语言 >c++知识点速刷

c++知识点速刷

时间:2022-09-07 10:12:36浏览次数:76  
标签:知识点 函数 右值 速刷 内存 c++ 对象 引用 指针

语法

指针和引用

指针:存放某个对象的地址 引用:变量的别名,从一而终,不可变,必须初始化

const变量

指针常量(底层const):指针所指的对象不可变 常量指针(顶层const):指针不可变

define和typedef的区别

define:
  1. 只是简单的字符串替换,没有类型检查
  2. 是在编译的预处理阶段起作用
  3. 可以用来防止头文件重复引用
  4. 不分配内存,给出的是立即数
typedef
  1. 有对应的数据类型,需要进行判断
  2. 在编译、运行的时候起作用
  3. 在静态存储区中分配空间

define和inline的区别

define:定义预编译时处理的宏,只是字符串替换,无类型检查,不安全。 inline:直接将函数体插入被调用的地方,减少了压栈,跳转和返回的操作。 内联函数是一种特殊的函数,会进行类型检查。

override和 overload

override:重写,覆盖 overload:通过不同的参数类型,不同的参数个数,不同的参数顺序进行重载。访问权限,返回类型,抛出的异常不进行重载 总结:重写只有一个,重载是将类似的函数用同一个名字,仅通过参数区分 多态是为了避免在父类中进行过多的重载

new和malloc

  1. new分配失败抛出异常,malloc返回nullptr
  2. new无需指定内存块的大小,malloc需要显示指出所需内存的尺寸
  3. new和delete可以重载,malloc和free不能重载
  4. new会调用对象的构造析构函数,malloc不会
  5. new是运算符,malloc是库函数

constexpr和const

constexpr:常量表达式 const:只读 constexpr的好处:确保某些数据无法被修改;部分场景编译器可以对constexpr做优化;比宏更安全,开销更少。

volatile

作用:要求编译器读取数据时,每次都从内存中重新装载内容,而不是从寄存器中拷贝

extern

定义:声明在函数或者文件外定义的全局变量

static

作用:实现多个对象之间数据的共享和隐藏;默认初始化为0

前置++与后置++

前置++返回左值(引用),后置++返回右值(临时对象)

std::atomic

作用:为了线程安全,使得原本线程不安全的语句变成“原子”语句,不再可分,从而实现线程安全。

访问权限

pubic:公有 protected:保护 private:私有 在类内(定义类的代码内),三种都可以访问。 在类外(定义类的代码外),只能访问public成员。 无论何种继承,派生类都不能访问私有成员。 对于公有继承,“派生类对象”只能访问基类中的公有成员。对于私有和保护继承,“派生类对象”无法访问基类的所有成员。 1. 继承 功能:在现有类的基础上,定义一个新的类,使得可以在无需重新编写的情况下,进行功能拓展。
  • 实现继承:使用基类的属性和方法,无需额外编码
  • 接口继承:仅使用属性和方法的名称,具体实现由子类提供
  • 可视继承:指子窗体类,使用了基窗体类的外观和实现。
2. 封装 功能:将数据和代码捆绑在一起,避免外界干扰和不确定性访问 3. 多态 功能:向不同对象,发送同一消息,不同对象会产生不同的行为 重载实现编译时多态,虚函数实现 运行时多态 总结:允许将子类类型的指针赋值给父类类型的指针。 多态的实现:
  1. override(重写,覆盖):子类重新定义父类的虚函数。
  2. override(重载):允许存在多个同名函数,通过不同的参数列表区分。

虚函数(virtual)

功能:当基类希望派生类自定义函数时,将该函数声明为虚函数。
  1. 虚函数是动态绑定的:使用虚函数的指针和引用可以找到实际类的对应函数
  2. 多态:前提条件(1)调用函数的对象必须是指针或者引用(2)被调用的函数必须是虚函数,且完成了重写
  3. 动态绑定绑定的是动态类型:虚函数对应的函数或属性依赖于对象的动态类型,发生在运行期。
  4. 构造函数不能是虚函数:在构造函数中调用虚函数,会执行父类的对应函数,因为自身还没有构造好,无法多态。
  5. 析构函数可以是虚函数,且在复杂类中,通常必须是虚函数。析构函数也可以是纯虚函数。
  6. 虚函数的工作方式:虚函数依赖虚函数表工作,表中保存虚函数地址,当用基类指针指向派生类时,虚表指针指向派生类的虚函数表
  7. 纯虚函数:有纯虚函数的类是抽象类,无法实例化。
  8. inline(编译时展开), static(静态), constructor(子类未构造) 三种函数不能为虚函数
  9. 派生类的虚函数重写定义必须与父类完全一致。
为什么需要虚继承 虚继承的本质是,让一个类共享他的基类。
  1. 解决多继承(从多个直接基类中产生派生类)的命名冲突和冗余数据问题。(实际中最好不要用多继承)
  2. 解决菱形继承,典型案例:iostream从istream和ostream直接继承而来,而istream和ostream各自继承自同一个类baseios。
空类 空类size为1,为了有地址,不同的空类地址不同 如果派生类继承的第一个是基类,且基类定义了虚函数表,则派生类共享该表首地址占用的存储单元。 抽象类与接口的实现 类中有任意一个函数被声明为纯虚函数,则这个类就是抽象类。纯虚函数通过在申明中使用” = 0“来指定。 设计抽象类(也称ABC)的目的,是为了创造一个不能实例化的基类,作为接口使用。

智能指针

shared_ptr 1.实现机制:在拷贝构造时使用同一份引用计数
  1. 模板指针:指向实际的对象
  2. 引用计数:使用new,存放在堆中
  3. 重载operator* 和operator->:实现指针的效果
  4. 重载copy constructor:引用计数+1
  5. 重载operator=:对右边的shared_ptr 调用析构函数,对左边的调用拷贝构造
  6. 重载析构函数:使应勇次数减一,当引用为0时,delete
2. 线程安全问题 同一个shared_ptr被多个线程“读”是安全的。 同一个shared_ptr被多个线程“写”是不安全的。 共享引用计数的不同的shared_ptr被多个线程“写”是安全的。 举例:现有三个shared_ptr,分别为s, a, b。其中s是多线程共享的,s指向对象A,a在线程1中,为空,b在线程2中,指向对象B。智能指针赋值有两步操作,1:指针赋值,2:引用计数加一。线程1先执行a=s,在完成指针复制后,a指向对象A,线程2抢占获得了运行资源,执行s=b,指针复制后,s指向对象B,b引用计数加一,对象A引用计数减一,归零,对象A被delete。此时,智能指针a指向了被销毁的对象,发生错误。 2. unique_ptr unique_ptr唯一拥有其所指的对象:同一时刻,只能有一个unique_ptr指向给定对象,离开作用域时,若其指向对象,则delete该对象 unique_ptr需要绑定new操作符分配的堆中的对象 不支持拷贝和赋值,但可以通过release和reset移交指针的所有权 3. weak_ptr 为了配合shared_ptr而引入的指针,可能查看对象,但不增加引用计数,和shared_ptr指向相同的内存。 功能:作为访问内存的工具,且不影响对象的生命周期 C++强制类型转换 关键字:static_cast, dynamic_cast, reinterpret_cast, cosnt_cast 1. static_cast 没有运行时类型检查来保证转换的安全性 进行上行转换(把派生类的指针,引用 转换为基类)是安全的。 进行下行转换,因为派生类可能有不属于基类的变量,所以是不安全的。 总结:静态转换,需要程序员自己确定转换的安全性。 2.dynamic_cast 具有类型检查(信息在虚函数中),更安全。转换后必须是类的指针、引用或者void*,基类要有虚函数。 dynamic本身只能用于存在虚函数的父子关系的强制类型转换;对于指针,转换失败则返回nullptr,对于引用,转换失败会抛出异常。 总结:当父类需要使用子类的函数,且父类自身的该函数不能设置为虚函数时(如果可以设置为虚函数,编译器会自动动态选择合适的版本)。使用时要加倍小心,尽量使用“定义虚函数”的方法。 3.reinterpret_cast 可以将整形转换为指针,也可以把指针转换为数组;可以在指针和引用间随意转换,平台移植性价比差。 4.const_cast 去掉类型的const或volatile属性。 总结:少用强制类型转换  

C++内存模型

字符串操作函数
char *strcpy(char *strDest, const char *strSrc);
//把src字符串拷贝到dest字符串上。
int strlen(const char *str);
//计算给定字符串的长度
char *strcat(char *dest, cosnt char *src);
//把src接到dest字符串的后面。
int strcmp(const char * s1, const char * s2);
//比较大小。s1 < s2 返回负数 = 返回0, >  返回正数
内存泄露 定义:程序未能释放掉不再使用的内存的情况,称为内存泄漏。可以使用Valgrind,mtrace进行内存泄漏检查 分类:(1)堆内存泄露:开辟的堆内存没有释放。(2)系统资源泄露:程序使用系统分配的资源(Bitmap, handle, SOCKET等),没有使用相应的函数释放,导致系统资源的浪费。(3)没有将基类的析构函数定义为虚函数,导致子类没有正常释放 常见情况:指针改变指向,未释放动态分配的内存 措施:将内存的分配封装在类中,构造分配,析构释放;使用智能指针   地址空间分布
  1. 命令行参数和环境变量:从命令行执行程序时,程序员指定的参数
  2. 栈区:存储局部变量、函数参数值。从高地址向低地址增长的连续空间
  3. 文件映射区:绑定动态库等
  4. 堆区:动态申请的内存。从低地址向高地址增长
  5. BSS段:存储未初始化的全局变量和静态变量
  6. 数据段:存储已初始化的全局变量和静态变量
  7. 代码段:存放程序代码的内存区,只读,头部包含一些只读的常数变量。
静态存储区:编译时分配,生存周期为整个运行期间,如全局变量,static变量。 栈:执行函数时,函数的局部变量都可以在栈上创建,生存周期为函数的运行时间,自动释放。 堆:程序员自己申请(new, malloc)和释放(free,delete),生存周期由自己决定。

 C++11新特性

类型推导

1.auto

作用:让编译器在编译期自动推导出变量的类型
  1. 必须初始化
  2. auto不能定义数组
  3. 不能推导出模板参数
  4. 在不声明为引用或指针时,会忽略等号右边的引用类型,和const, volatile类型。
  5. 声明为引用或指针时,会保留。

2. decltype

decltype用于推导表达式类型。 decltype会保留引用和cv属性(const,volatile) 对于decltype(exp)有:
  1. exp是表达式,decltype(exp)和exp类型相同
  2. exp是函数调用,decltype(exp)和函数返回值类型相同
  3. 其他情况,若exp是左值,decltype(exp)是exp类型的左值引用
例子
template <typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
    return t + u;
}

右值引用

定义:右值引用就是必须绑定到右值的引用,通过&&来获得右值引用。 性质:只能绑定到一个将要销毁的对象,于是,我们可以自由地将一个右值引用的资源绑定到另一个对象中。 常规的引用,我们可以称之为左值引用。

1.左值右值

左值:有地址,可以放在等号左边 右值:没有地址,不可以放在等号左边(字面量,临时量)
++i, --i 是左值,i++, i-- 是右值。

2.右值引用

右值有两个特性:所引用的对象将要被销毁;该对象没有其他用户 这意味着:使用右值引用的代码可以自由地接管所引用的对象的资源 右值引用本身是一个左值:接管资源后,资源就有了地址和用户,因此,右值变成了左值。

3.std::move

虽然不能把右值引用绑定到左值上,但可以使用std::move把一个左值转化为对应的右值引用类型。 浅拷贝:拷贝指针 深拷贝:重新开辟内存,并复制内容

nullptr

nullptr:特殊类型的字面量。 用来替代NULL和0。NULL在有的编译器中定义为((void*)0),有的定义为0。因此,NULL具有二义性,在下面情况会发生问题。
void test(char*);
void test(int);
使用test(NULL)时,编译器会不知道使用哪一个重载。

范围for循环

for (auto c : string) {
    cout << c;
}
可以简化遍历。

列表初始化

double d = 3.124564564654
int a = {d};
int a = d;
使用花括号来进行初始化称为列表初始化。 对于内置类型,使用列表初始化时,如果存在丢失信息的风险,编译器会报错。

lambda表达式

表示一个可调用的代码单元,可以理解为没有命名的内联函数,用于一次性的场景。

1.语法

[capture list] (parameter list) ->return type {functon body}
我们可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体。

2.变量捕获

  1. []不捕获
  2. [&]引用捕获
  3. [=]拷贝捕获
  4. [=, &foo]引用捕获foo,拷贝捕获其他
  5. [bar]拷贝捕获bar
  6. [this]捕获所在类的this指针

3.lambda使用algorithm库

std::sort(arr, arr+6, [](int &a, int &b){return a > b});
     

标签:知识点,函数,右值,速刷,内存,c++,对象,引用,指针
From: https://www.cnblogs.com/yuan-sen/p/16664305.html

相关文章

  • 强化学习——价值迭代算法 悬崖漫步为例 C++
    #include<bits/stdc++.h>usingnamespacestd;#defineN100#definecliffcliff_mapintrow,col;structState{intnext_i,next_j,flag;doublereward;......
  • vc++ get random via random_device,mt19937
     #include<ctime>#include<iostream>#include<random>usingnamespacestd;staticrandom_devicerd;staticmt19937mt{rd()};template<typenameT>vo......
  • [C++]类名加个括号是什么东东
    先考考大家,下面的代码,编译得过吗?classMyClass{public:MyClass(){printf("MyClass\n");}};int_tmain(intargc,_TCHAR*argv[]){......
  • 计算机网络面试知识点总结
    计算机网络tcp/ip五层模型tcp和udp的区别UDP头部包含了以下几个数据:两个十六位的端口号,分别为源端口(可选字段)和目标端口整个数据报文的长度整个数据报文的检验和......
  • ECX知识点
    文章不易,请关注公众号 毛毛虫的小小蜡笔,多多支持,谢谢。有任何问题都可以留言咨询。 背景有个解决方案的同事走过来,看了下我电脑界面上的展示。然后问了几个问题,都是......
  • Java调用C++动态链接库——Jni
    最近项目需要,将C++的算法工程编译成动态链接库,交给Java后台当作函数库调用。就去了解了下Jni。使用起来还是比较方便的。1.  首先编写Java的调用类。例如:  public......
  • 记刷题过程中发现的C++与C的差异
    前言上大学了,学c。标题嫖自@快乐永恒正题01#include<stdio.h>intmain(){longlonga,b;scanf("%lld%lld",&a,&b);printf("%lld%lld%lld%lld%l......
  • conda环境报错:libgomp.so.1: version `GOMP_4.0' not found?libstdc++.so.6: version `
    问题之前的conda环境好好地,最近不知为何被破坏了,运行即报错:/miniconda3/opt/lib/R/bin/exec/R:/miniconda3/opt/lib/R/bin/exec/../../lib/../../libgomp.so.1:version......
  • C++ 初识函数模板
    1.前言什么是函数模板?理解什么是函数模板,须先搞清楚为什么需要函数模板。如果现在有一个需求,要求编写一个求2个数字中最小数字的函数,这2个数字可以是int类型,可以......
  • c++STL用法总结
    一、vector的用法vectorvet;1、排序:sort(vet.begin(),vet.end()),时间复杂度O(nlogn)2、查找:if(find(vet.begin(),vet.end(),x)!=vet.end()),时间复杂度O(n)......