C++基础回顾(上)

news2024/12/24 2:15:36

C++基础回顾(上)

目录

  • C++基础回顾(上)
    • 前言
    • 关键字和标识符
    • 运算符
    • 数据类型
    • 函数

封面

前言

C++之前学过一点,但是很长时间都没用过,翻出了书从头看了一遍,简短地做了笔记,以便自己之后查看和学习。

关键字和标识符

C++标识符是由字母、数字、下画线组成的,而且必须以字母或下画线开头

程序的约定俗称:

  • 对象名一般用小写字母;

  • 单词之间可用下划线或者每个单词首字母大写

字符型char用来保存机器基本字符集中对应的整数值,即该字符的ASCII码值

访问一个对象所在内存空间中的数据,需要知道其内存空间所在的内存地址,这通过对象的名字来实现。也就是说对象名本质上是内存地址的一个映射。

创建对象时最好提供一个初始值,以完成初始化。使用未初始化的对象是很危险的,有可能引起严重错误。

const修饰符

  • 不希望对象的内容发生变化

  • const对象创建后,其值不能再改变,因此const对象必须初始化。

typedef

typedef double price //price 是double的一个类型别名

using 关键字也可以声明别名

using price = double; //price 是double的一个类型别名

auto 关键字被利用来根据初始值的类型自动推导出需要的数据类型

左值所在的内存空间的地址是可以获取的,而右值的地址是无法得到的。

运算符

<< 输出运算符

>> 输入运算符

自增和自减运算符

int i=0;
i++;
++i; //这两个的作用都等同于i=i+1
//但是他们放到表达式中就不同了
int j;
j=i++;//先赋值,再自增,即j=0,i=1了
j=++i; //先自增,再赋值,即j=1,i=1了
//自减运算符类似

符号优先级:逻辑非最高,其次是关系运算符,最后是逻辑与和逻辑或

条件运算符?: 三目运算符

cond?expr1:expr2判断cond表达式,真则返回expr1,假则返回expr2

{

} //用花括号括起来的语句是复合语句,构成一个语句块,在块中引入的名字只能在块内可见。

数据类型

复合类型: 指针、引用、数组、函数、联合体、枚举类型

引用:

  • 为已经创建的对象重新起一个名字,编译器只是将这个别名绑定到所引用的对象上,不会复制对象的内容给引用。

  • 相当于还是那一块内存,只不过这个内存的名字多了,比如小明还可以叫明明。

    int counter=0;
    int &refCnt =counter; //refCnt引用counter对象的内容
    
  • 右值引用:C++11新引入。可以操控右值对象了,尤其是编译器产生的临时对象

    int i=0;
    int &&rr1=i+1; //右值引用,绑定到一个临时对象,临时对象的生命期得到了延续,续命了。
    

指针:

  • 存放的是数据的内存地址,然后通过这个对象对数据进行访问。这种专门用来存放地址的对象称为指针对象。

    int i =100;
    int *ptr=&i; //&在这里是取址符 现在ptr对象里存放的就是i的地址。
    
  • 要访问i的内容,需要通过解引用操作符*来实现

    *ptr=10; //读取对象i的内容
    
  • 避免使用野指针,如果指针对象在定义时没有具体的指向对象,则需要用nullptr来初始化。

    {
    int *ptr1 =nullptr; //空指针
    int *ptr;  //野指针
    }
    
  • 多级指针

    把一个指针对象的地址存放到另一个指针对象中,则形成了指向指针的指针

    int i=1, *ptr =&i;
    int **pptr =&ptr; //指向指针的指针,pptr中存储的是ptr的地址,而ptr中存放的是i的地址
    
  • 引用可以看作是支持自动解引用操作的const指针

数组

  • 数组是有限个同类型元素组成的有序集合,所有元素顺序存放在一段连续的内存空间中。

    int arr[5] //存储5个整型元素的数组

  • []中的值必须是大于0的整型常量表达式

    unsigned cnt =10;
    int arr[cnt];  //不能这样定义,cnt并不是常量表达式
    constexpr int sz =10;
    int arr[sz]; //可以
    
  • 字符数组会在末尾自动添加字符串结束符’\0’

  • 举例

    inr arr[5] ={1,2,3,4,5};
    for (auto i:arr){  //auto自动推断数据元素的类型
    	cout<< i<<endl;
    } //这里只能进行读操作,因为i只是一个临时对象,他与数组arr并没有产生实际上的联系,我觉得
    
    //可以进行写操作的例子
    for (auto &i:arr){
    	i=0;
    } //此时i是引用了,相当于arr的别名,映射的地址都是相同的,因此对i赋值,能够修改arr的内容
    
  • 多维数组

    int a2d[3][5]; //二维数组 3*5
    
  • 指针指向数组

    一般情况下,编译器对数组的操作都会转换成对指针的操作,数组名通常被转换成数组第一个元素的地址

    int arr[] ={1,2,3,4,5};
    int *p =arr; //arr被转换成arr[0]的地址
    int *p =&arr[0]; //与上一句等价
    
    
  • 可以用指针访问数组,比如移动指针位置,从而访问数组中的其他数据。但要注意,指针运算过程中不能超出数组的范围了,不然就不知道指向的地址是哪里了。

vector

  • 容器类型,能够存放类型相同的元素,但是支持变长操作,对容量大小可根据需要进行动态调整。

  • 定义和初始化

    vector<int> v1; //存放整数的空vector
    vector<int> v2={0,1,2}; //存放三个int元素的vector
    
  • vector<int> vi;
    vi.push_back();  //尾部插入一个元素
    vi.pop_back(); //尾部删除一个元素
    vi.clear(); //移除所有元素
    vi.at(1) //访问vi的第二个元素
    
  • 迭代器

    为了支持随机访问, vector中有一个叫迭代器的东西,通常借助容器的成员函数begin和end获取

    vector<int> vi={0,1,2,3};
    auto itb=vi.begin(); //itb指向vi的第一个元素
    auto ite=ci.end(); //ite指向vi的尾后元素
    //itb和ite都是vector<int>::iterator的迭代器类型
    

    迭代器与指针类似,可以通过解引用来获取指向对象的内容。

    for (auto it=vi.begin();it!=vi.end();++it){
    	*it *=2; //每个元素乘2
    	cout<<*it<<endl;
    }
    

枚举类型

  • 不限定作用域和限定作用域方式的枚举类型

  • 不限定作用域的枚举类型和限定作用域的枚举类型

    enum color{red,green,blue}; //enum关键字来定义不限定作用域的枚举类型 
    enum class  stoplight{red,green,yellow}; //enum class 来定义限定作用域的枚举类型
    color c =red; //访问color的枚举成员,限定作用域的不能这样访问了
    stoplight b =stoplight::red; //访问限定作用域的枚举类型
    stoplight a =red; //不行
    
    

函数

一个函数的定义由四部分组成:返回值类型、函数名、形参列表和函数体。错误分为语法错误和逻辑错误。

int main(){
	return 0;
}

函数调用过程中,相对应的实参类型和形参类型必须匹配。

和对象的名字一样,函数的名字必须在使用之前声明。和函数定义不同,函数声明只需要描述函数的返回类型、名字和形参类型即可。

int maximum(int a ,int b); //因为声明没有函数体,因此形参名称也是可以省略的
int maximum(int, int);

一般来说,函数或对象声明放在头文件,相应的定义放在源文件。

局部对象和全局对象

​ 存储周期:对象在内存中存储的时间

存储周期类型作用周期存储位置
自动存储周期定义位置在内存中创建,离开作用域时释放
静态存储周期static关键字声明的对象,程序运行期间,始终存在全局数据区
动态存储周期new运算符生成的对象,delete释放内存空间
线程存储周期thread_local关键字创建的对象,在其所在的线程创建时开始,线程结束时释放

全局对象具有外部链接性,可以在其他的文件中访问

int g_val =10; //g_val在fun.cpp中定义的全局对象,具有外部链接性
extern int g_val; //extern声明可以使得main.cpp也能访问到g_val
static int gs_val=20; //静态对象,在外部访问不了
int main(){
	cout <<g_val+gs_val;
} //输出30

参数传递

函数的实参和形参的交互方式:单向的值传递,双向的引用传递

单向的值传递中,函数的形参发生变化,不会影响到实参

void Swap(int x,int y){
	int z(x);
	x=y;
	y=z;
}//形参x y交换

int i(4),j(5);
Swap(i,j);
cout<<i<<j<<endl; //实参 i j的内容并没有被改变

地址传递,可以通过形参改变实参的值。

void Swap(int *x,int *y){
	int z(*x);
	*x=*y;
	*y=z;
}//形参x y所指向的地址的内容交换

int i(4),j(5);
Swap(&i,&j); //取址符
cout<<i<<j<<endl; //实参 i j的内容交换了

引用传递,类似地址传递

void Swap(int &x,int &y){ //引用,即别名
	int z(x);
	x=y;
	y=z;
}//形参x y内容交换

int i(4),j(5);
Swap(i,j); 
cout<<i<<j<<endl; //实参 i j的内容交换了

const形参

const形参好像在程序应用很广泛

void fun(const int i); //只可以读i,不可写
void fun(const int *i); //可以更改i的指向,但是改不了指向的地址的内容
void fun(const int &i); //只读,不可写

上述值传递对于实参是安全的,但是对于数据大的对象复制操作低效;引用可以避免复制,但是实参不安全;const 引用形参安全高效。

向main函数传递实参

//main函数有两个可选的形参
int main(int argc,char*argv[]){

}
//第一个形参argc的值是argv的元素的个数,第二个形参是一个数组,每个元素是指向C风格字符串的指针 
//argv[0]保存的是可执行程序的名字,可选实参从argv[1]开始

函数重载

  • 统一作用域下具有相同名字,但是不同形参列表的一组函数称为重载函数

    const int & getMax(const int &a,const int &b){} //这里的值返回的是一个int常量的引用
    const int & getMax(const int &a,const int &b, const int &c){} //重载
    const string & getMax(const string &a,const string &b){} //重载
    

默认函数

void turnoff(int time =21); //声明的时候给出了默认形参,调用时不提供实参,则采用默认值21

内联函数

inline void Swap(int &x,int &y){}; //inline关键字定义内联函数,直接在调用处嵌入内联函数代码,不发生函数调用,不产生函数调用开销,但对编译器只是建议

lambda表达式

  • lambda表达式可以理解为一个临时的匿名函数,表示一个可以调用的代码单元

    [captures](parameters)-> return type{statements}
    //parameters 、return type 、statements分别代表形参列表、返回值类型和函数体
    //[]代表lambda引导,captures子句指定在同一作用域下lambda主体访问哪些对象以及如何捕获这些对象,可以为空
    
    int divisor=5;
    vector <int > numbers{ 1,2,3,4,5,10,15,20,25,35,45,50);
    for each(numbers,begin(),numbers.end(),[divisor](int y){
    	if(y%divisor==0) //divisor 为外围divisor 的副本
    		cout <<y <<endl;//输出被 divisor整除的元素
    });
    

宏定义

  • 功能是定义一个标识符来代替一串字符,该标识符为宏名

  • #define 宏名 字符串常量
    #define PI 3.1415926
    

  • 类是用户自定义类型数据,基本思想是抽象和封装

  • 类是对一个事物的属性和操作的描述。例如对于一个分数类来说,基本属性有分子和分母,操作包括约分、计算分数值等操作。

    class Fraction{ //Fraction是类名 有两个数据成员和5个成员函数
    	//数据成员
    	int m_fenzi=0; //分子,默认值为0
    	int m_fenmu=1; //分母,默认值为1
    public: //public关键字后的成员时对外公开的,在程序的任何地方都可以访问
    	//成员函数
    	int fenzi() const{return m_fenzi;} //这里在圆括号后面引入const关键字是说明对this指针指向的const对象的数据成员进行写操作是非法的。
    	int fenmu() const{return m_fenmu;}
    	double value() const; //计算分数值
    	void reduce(); //约分
    private: // private 私有成员函数,只能在类的内部使用 
        //值得注意的是,不显式指明成员的访问属性,访问属性默认private
    	int gcd(int x, int y); //计算x和y的最大公约数
    
    }; //类中只有成员函数的声明,定义最好放在类外面
    
    double Fraction::value() const{
    	return static_cast<double> (m_Fenzi)/m_fenmu;
    } //成员函数value 的定义
    
    Fraction a;
    a.value(); 
    a.value(&a); //这两句是等价的,意思是当通过对象调用成员函数时,有一个隐式的指针类型形参this接受了调用对象的地址
    double value(Fraction *const this)const; //value 成员函数的声明自动转换为该形式,一个隐式的指针类型形参this
    

    struct关键字也可以用来定义一个类,使用struct定义中的类成员的访问属性默认为public

  • 友元函数

    不是类的成员却可以访问类的非公有成员。

    class Fraction{
    	friend ostream &print(ostream&os, const Fraction &a); //friend关键字声明友元函数
    };
    
  • 友元类

     class cricle; //类的前向声明
    class rectangle{
    	friend class cricle; //友元类
    }; 
    //友元都是单向传递的,你是我的朋友,但我不是你的朋友
    
  • 构造函数与析构函数

    类类型对象的初始化过程是由一类特殊的成员函数完成的,称为构造函数

    构造函数帮助对象创建时为数据成员执行初始化操作,只要创建类类型对象就会执行构造函数

    构造函数:1. 函数名和类名一致;2. 无返回值;3. 不能声明为const成员函数

    class Fraction{
    	public:
    		Fraction()=default; //默认构造函数
    		Fraction(int above, int below):m_fenzi(above),m_fenmu(below){} //显示定义构造函数,但是也是默认构造函数
    		Fraction(int above, int below){
    			m_fenzi=above;
    			m_fenmu=below;
    		}//这一个等同于上一个构造函数,但是上一个在m_fenzi和m_fenmu创建时就初始化了,这个还要再赋值一下,上一个执行效率更高。
    };
    

    析构函数

    class Fraction{
    	public:
    		~Fraction(){} //析构函数
    };
    
  • 静态成员:可以通过static关键字声明静态成员,但该成员是共享的,类对象不包含静态成员

    class Fraction{
    	pulic:
    		static int num;
    };
    Fraction a ;//a成员中不包含num这个成员
    

    如果您觉得我写的不错,麻烦给我一个免费的赞!如果内容中有错误,也欢迎向我反馈。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/418187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5、存储引擎

1、查看存储引擎 查看mysql提供什么存储引擎&#xff1a; show engines;2、设置系统默认的存储引擎 查看默认的存储引擎&#xff1a; show variables like %storage_engine%; #或 SELECT default_storage_engine;修改默认的存储引擎 如果在创建表的语句中没有显式指定表的存…

教你精通Java语法之第十二章、递归

目录 一、递归 1.1递归的概念 1.1.1定义 1.1.2原理 1.1.3思路 1.2单路递归 1.2.1阶乘 1.2.2正向输出数字 1.2.3反向输出字符串 1.3多路递归 1.3.1斐波那契数列 1.3.2兔子问题 1.3.3青蛙爬楼梯 1.4汉诺塔问题 1.5猴子吃桃问题 1.6老鼠走迷宫问题 二、递归的时…

从视频中截取gif怎么弄?三步简单完成视频转gif制作

电影、电视剧等短视频充斥着我们的生活&#xff0c;很多小伙伴会将这些视频中的有趣画面提取出来做成Gif动画表情包。那么&#xff0c;怎么才能从视频中提取gif动画呢&#xff1f; 一、使用什么工具才能从视频中提取gif呢&#xff1f; 通过使用GIF中文网这款专业的视频转gif&…

RabbitMQ (工作队列:Work Queues)

本章目录&#xff1a; 什么是Work Queues模拟场景&#xff0c;使用Work Queues官网文档&#xff1a;RabbitMQ tutorial - Work Queues — RabbitMQ 一、何为Work Queues 我们先看下它的结构图 显然&#xff0c;它与入门案例相比只是多了几个消费者。 以下是官方文档说明 In …

【目标检测】目标检测遇上知识图谱:Object detection meets knowledge graphs论文解读与复现

前言 常规的目标检测往往是根据图像的特征来捕捉出目标信息&#xff0c;那么是否有办法加入一些先验信息来提升目标检测的精准度&#xff1f; 一种可行的思路是在目标检测的输出加入目标之间的关联信息&#xff0c;从而对目标进行干涉。 2017年8月&#xff0c;新加波管理大学…

Vue——插槽

目录 插槽内容与出口​ 渲染作用域​ 默认内容​ 具名插槽​ 动态插槽名​ 作用域插槽​ 具名作用域插槽​ 高级列表组件示例​ 无渲染组件​ 插槽内容与出口​ 在之前的章节中&#xff0c;我们已经了解到组件能够接收任意类型的 JavaScript 值作为 props&#xff0c;…

微信小程序 | 基于ChatGPT实现电影推荐小程序

文章目录** 效果预览 **1、根据电影明星推荐2、根据兴趣标签推荐3、根据电影名推荐一、需求背景二、项目原理及架构2.1 实现原理&#xff08;1&#xff09;根据用户的兴趣标签&#xff08;2&#xff09;根据关联类似主题的题材&#xff08;3&#xff09;根据特定的电影明星2.2 …

IK集成ElasticSearch,IK分词器的下载及使用

IK集成ElasticSearch&#xff0c;IK分词器的下载及使用 下载ElasticSearch 8.7.0网址&#xff1a;Download Elasticsearch | Elastic 历史版本地址&#xff1a;Past Releases of Elastic Stack Software | Elastic 解压ElasticSearch 什么是IK分词器 分词∶即把一段中文或…

IO流基础

目录 1.FileOutPutStream字节输入流 1.1FileOutPutStream使用 1.1.1创建对象 FileOutPutStream fos new FileOutPutStream("路径或者File对象")&#xff1b; 1.1.2.写数据 调用write方法&#xff0c;参数是int类型&#xff0c;但传入文件中是asci…

【LeetCode: 剑指 Offer II 112. 最长递增路径 | 递归 | DFS | 深度优先遍历 | 记忆化缓存表】

&#x1f34e;作者简介&#xff1a;硕风和炜&#xff0c;CSDN-Java领域新星创作者&#x1f3c6;&#xff0c;保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文|经验分享|好用的网站工具分享&#x1f48e;&#x1f48e;&#x1f48e; &#x1f34e;座右…

海康工业相机网口相机丢包问题解决方法

​1.1 系统环境设置 1.1.1 网卡设置 网卡推荐使 Intel 芯片的独立千兆网口,例如 intel I350、I210 等芯片组网卡 设置网卡巨型帧为选择 9KB 或 9014 字节 *不同网卡类型,网卡属性有差异,需灵活参考 设置网卡接收与传输缓存区到最大(intel 网卡一般为 2048,realtek 一般…

Program tuning - Druid和Linux配合优化数据库连接池配置

Program tuning - Druid和Linux配合优化数据库连接池配置配置步骤1. 添加依赖2. 添加配置3. 启动监控界面常见问题输入地址之后&#xff0c;浏览器直接打印html代码&#xff0c;而不是登录框刷新页面不能重新加载数据调优步骤1. 开始压测2. 监控线程池状态3. 查看服务器状态结论…

算法 贪心5 || 435. 无重叠区间 763.划分字母区间 56. 合并区间 738.单调递增的数字 968.监控二叉树

435. 无重叠区间 和452. 用最少数量的箭引爆气球 思路是很相似的。本题按照左边排序或者按照右边排序都是可以的&#xff0c;最终目的都是为了让区间尽可能重叠。 1、按右边排序&#xff0c;排序完第一个元素的右边界一定是最小右边界。往下找第一个不与其重合的左边界&#x…

亚马逊云科技为全球的可持续发展进程做出贡献

可持续发展是一个涉及经济、环境和社会三个方面的复杂问题。经济发展必须在保护环境和社会公正的前提下进行&#xff0c;这样才能实现真正的可持续发展。为了实现这一目标&#xff0c;人们需要借助技术手段&#xff0c;更好地理解和解决环境和社会问题。 亚马逊云科技是全球领…

nssctf web入门(2)

目录 [SWPUCTF 2021 新生赛]easy_md5 [SWPUCTF 2021 新生赛]include [SWPUCTF 2021 新生赛]PseudoProtocols 这里通过nssctf的题单web安全入门来写&#xff0c;会按照题单详细解释每题。题单在NSSCTF中。 想入门ctfweb的可以看这个系列&#xff0c;之后会一直出这个题单的解…

到了这个年纪,就应该阅读Spring源码了,源码阅读指南-编译加运行

文章目录到了那个年纪&#xff0c;就应该阅读Spring源码了&#x1f604;第一步&#xff0c;clone&#x1f606;第二步&#xff0c;使用idea打开项目&#x1f60a;gradle介绍&#xff08;插叙手法&#xff09;&#x1f603;第三步&#xff0c;修改gradle的远程仓库地址&#x1f…

Day932.5个步骤,高效推动组件化架构重构 -系统重构实战

5个步骤&#xff0c;高效推动组件化架构重构 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录都是关于5个步骤&#xff0c;高效推动组件化架构重构的内容。 项目的架构设计是一回事&#xff0c;代码落地又是另外一回事&#xff0c;很多架构设计最终都只是落在了 PPT 上。 一…

QT Graphics View坐标系转换

背景 在做绘图处理时&#xff0c;Scence作为场景&#xff0c;大小是无限的&#xff0c;而View作为一个观察镜头&#xff0c;观察范围是有限的。 那么有限的View观察无限的Scence区域&#xff0c;必然要选定一个观测锚点。 所以View具有一个centerOn(QPointF pos)函数&#xff…

Linux-初学者系列——篇幅1_文件管理命令(持续更新中)

Linux-初学者系列_篇幅1 文件管理命令-目录Linux-初学者系列_篇幅11.创建文件语法&#xff1a;示例&#xff1a;2.创建目录语法&#xff1a;示例&#xff1a;注意&#xff1a;常见错误&#xff1a;3.复制语法&#xff1a;示例&#xff1a;补充&#xff1a;4.移动语法&#xff1…

Vue|数据渲染

Vue 是如何将编译器中的代码转换为页面真实元素的&#xff1f;在Vue 中,自带了模板渲染,而模板的语法也非常简洁易懂。 精彩专栏持续更新↓↓↓ 微信小程序实战开发专栏 一. 数据渲染1.1 条件渲染v-ifv-show1.2 列表渲染v-for1.3 小结一. 数据渲染 1.1 条件渲染 vue条件渲染指…