写在前面

写本系列的目的(自用)是回顾已经学过的知识、记录新学习的知识或是记录心得理解,方便自己以后快速复习,减少遗忘。以前三天打鱼两天晒网地学习C++,一直无法对C++熟练掌握,核心的面向对象编程并不熟悉,STL语法只会部分,因此也希望自己未来能做到熟悉甚至精通C++。

由于我有部分编程语言学习经验,因此基础的部分只是通过“C++菜鸟教程”来进行简单的回顾,只进行语法的罗列。

Part 1 知识回顾

该部分通过“C++菜鸟教程”来进行简单的回顾,因为这部分是我比较熟悉的部分,因此只进行语法的罗列,涉及到底层原理的内容不多赘述,内容基本都来自于C++菜鸟教程。

一、C++基本语法

1、基本概念

C++中有几个重要概念:对象、类、方法、即使变量。

类:类可以定义为描述对象行为/状态的模板/蓝图。例如,创建一个狗的类就是定义了“狗”这个类别的模板,里面包含描述狗的各类信息,如颜色、品种等。

对象:对象具有状态和行为。例如:在“狗”类中定义了具体的状态 - 黑色、拉布拉多,这就是对象。对象是类的实例。

方法:从基本上说,一个方法表示一种行为。一个类可以包含多个方法。可以在方法中写入逻辑、操作数据以及执行所有的动作。

即使变量:每个对象都有其独特的即时变量。对象的状态是由这些即时变量的值创建的。

2、关于using namespce std;

这段程序告诉编译器使用 std 命名空间,在未来开发过程中可以尽量少用using namespace std,因为在开发过程中可能不止使用一个命名空间,不同的命名空间中可能会存在同名函数,这样在使用时就无法知道自己使用的是哪个命名空间的函数。此时直接使用std::cout会更加直观,不易出错。更加底层的东西,如汇编、编译、链接等在Cherno的C++视频教程里有详细的教学。

3、C++的注释

//这是单行注释

/*

这是多行注释

*/

/*  也可以单行使用  */

//在vs中也支持快捷键批量注释
//批量注释:Ctrl+K,Ctrl+C
//取消注释:Ctrl+K,Ctrl+U
//运用快捷键时,当你选中的为完整的行,每行“//”注释,若不完整的行会用/*...*/

二、类型

一些基础的类型或者是很少见的类型此处不列出了,未来遇到问题再回来补充。

1、枚举类型

枚举类型(enumeration)是C++中的一种派生数据   类型,它是由用户定义的若干枚举常量的集合。 枚举本质上是用来让代码变得更加清晰简洁的,枚举是整数。

enum Example1
{
    A,B,C
};
//这样默认A是0,B是1,C是2

enum Example2
{
   A = 7,B,C
};
//这样默认B为8,C为9

enum Example3 : unsigned int 
{
    A = 0, B = 1, C = 2;
};
//可以指定变量类型,但是必须是整数类型


int main()
{
    Example1 value = B;
    //不可以这么写 Example1 value = 1;
}

2、变量定义

C++的变量定义比C语言灵活

int i, j, k;
char c, ch;

int d = 3, f = 5;
char x = 'x';

第一种定义方式是不带初始化的定义,此时带有静态存储持续时间的变量会被隐式初始化为 NULL(所有字节的值都是 0),其他所有变量的初始值是未定义的。

3、声明

变量声明向编译器保证变量以给定的类型和名称存在,这样编译器在不需要知道变量完整细节的情况下也能继续进一步的编译。如下程序所示:

#include<iostream>
using namespace std;

extern int a, b;

int main()
{
    int a, b;
    a = 10;
    b = 20;
    cout<<a+b<<endl;
    return 0;
}

在程序中,可以使用 extern 关键字在任何地方声明一个变量,在此处变量在头部就被声明,而实际的定义与初始化在主函数中。同样的,也可以进行函数声明。

int func();

int main()
{
    int i = func();
}

int func()
{
    return 0;
}

在这段程序中,如果没有在main函数前声明函数func(),这段程序不能通过编译,需要将func()函数的函数体放在main()函数的前面。这就是声明的意义,可以让程序更加易读。

4、左值和右值 

左值:指向内存位置的表达式被称为左值表达式。左值可以出现在赋值号的左边或右边。

右值:右值指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。

int a = 1;
1 = 2;//错误的

 三、常量

常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。常量的值在定义后不能修改。

1、整数常量

整数常量可以带前后缀。

前缀:0x或0X表示十六进制,0表示八进制。不带前缀则为默认十进制。

后缀:U表示无符号整数,L 表示长整数。后缀可以是大写,也可以是小写,U 和 L 的顺序任意。

123           //十进制
0777          //八进制
0x4b          //十六进制
23u           //无符号整数
34l           //长整数
183ul/183lu   //无符号长整数
763ll         //非法,不能重复后缀
078           //非法,8不是八进制数字

2、浮点常量

浮点型常量由整数部分、小数点、小数部分及指数部分构成。基本格式为,正号可省略,小数点或指数部分可部分省略但不可同时缺失。其中,e或E表示的是10的阶码次方,e后的数字为阶码

1.2E+5
1.5e-9
-5.0e10
5e3            //小数部分非必须,可以没有
9.E5           //小数点后,阶码前的整数可以不写
.96e-8         //小数点前的阶码可以不写
56.            //非法
.5             //非法

3、布尔常量

 true为真,也可看为非0的所有数。false为假,可看为0。

4、字符串常量

字符串常量通常在双引号中。

string str = "Hello World!";

5、字符常量

字符常量通常在单引号中。转义序列也是一个字符常量。

char a = 'x';
char b = '\n'; //转移序列也看作一个字符常量

6、定义常量 

可以用#define预处理器定义常量的形式

#define pi 3.14

在使用定义常量时,实际使用的代码中会直接将“pi”替换为“3.14”,因此不需要等号或是“;”一类。如果使用 #define end ; 那么你的代码语句也可以写成 int a=1end...(不嫌麻烦的话

四、运算符

1、算数运算符

+,-,*,/,%,++,--

a = 1;
b = a++;  //b等于a,也就是1。a再++,a为2
b = ++a;  //a先自增,为3,b再等于a,也就是3

2、关系运算符

==:检查两个操作数的值是否相等,注意一定不要和赋值运算符=混用。

!=,>,<,>=,<=

3、逻辑运算符

&&,||,!:逻辑与、逻辑或、逻辑非。

4、位运算符

位运算符作用于位,并逐位执行操作。分别是&,|,^:与、或、非

例如,A=60,B=13;

则A的二进制为:0011 1100,B的二进制为:0000 1101。

A&B = 0000 1100,A|B = 0011 1101,A^B = 0011 0001,~A  = 1100 0011。

位运算在一些算法中会使用。

5、赋值运算符

=、+=、-=、*=、/=、%=

<<=:左移(左移二进制)且赋值、>>=、&=、^=、|=

6、杂项运算符

sizeof:返回变量大小,sizeof(a)返回a占内存的大小

Condition ? X:Y,条件运算符,如果Codition为真,返回X,否则返回Y

.和->,成员运算符,用于类、结构等中

五、循环与判断

1、循环

一共有while、for、do...while三种循环,以及嵌套循环

//while循环
int x = 5;
while(x>0)    //假如x>0,循环条件成立,一直执行while中的内容,直到x=0或x<0
{             //while中也可以没有循环条件,这样就会是个无限循环,除非用break终止循环
   x--;
{

//for循环
for(int i = 0; i < 10; i++)    //for中第二个为条件,三种条件可以自由决定写不写,也可以写多个
{
    cout<<"Hello, World!"<<endl;
}
for(int i = 0; j = 10; i < j; i++, j--) {}

//do while循环
int a = 0;
do{              //循环中的条件无论如何都会执行一次,然后再在while中进行判断
    a--;
}while(a>0);

2、循环控制语句

有三种循环控制语句,break,continue, goto

//break
int a = 1;
while()     //当条件成立时,break将会跳出循环,执行循环以后的语句
{
    if(a>10) break;
    a++;
}

//continue
int a = 1;
while(a<=10)          //continue不会跳出整个循环,只会跳过当前循环,进入下一个循环
{
    if(a%2) continue;
    cout<<"a是奇数"<<endl;
    a++;
}

//goto语句用于无条件跳转到同一函数内的另一个标签位置
int a = 1;
while(){
    if(a>10) goto exit_loop;
}
exit loop:
    cout<<"循环已退出"<<endl; 

3、判断语句

一共有三种判断语句:if、if...else、switch语句以及它们的嵌套语句。

//if语句
int a = 1;
if(a>0) cout<<"a是正数"<<endl;  //if后紧跟着布尔表达式,为真则执行if语句

//if...else语句
int a = 1; 
if(a>0)  
    cout<<"a是正数"<<endl;      //if后紧跟着布尔表达式,为真则执行if语句,否则执行else语句
else 
    cout<<"a不是正数"<<endl;

//switch语句
int a = 10, b = 5;
char op = '+';

switch (op) 
    case '+':
        cout << a + b << endl;   
        break;                  //注意,这里必须加上switch,否则语句将继续执行下去,不会跳出
    case '-':                   //也可以利用这一点实现"贯通"
        cout << a - b << endl;
        break;
    case '*':
        cout << a * b << endl;
        break;
    case '/':
        cout << a / b << endl;
        break;
    default:
        cout << "无效的运算符" << endl;
}

switch (op)                      //贯通示例
    case '+':
    case '-':                   
        cout << "加减运算符" << endl;
        break;
    case '*':
    case '/':                   
        cout << "乘除运算符" << endl;
        break;
    default:
        cout << "无效的运算符" << endl;
        
}

//condition ? x:y示例
int a = 1, b = 2;
c = a > b ? a : b       //c用来存储a,b中较大的数,a大于b吗?是的话c=a,不是的话c=b
d = a < b ? a : b  

六、函数

函数是一组一起执行一个任务的语句。每个 C++ 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。

这是一个简单的函数实例

int max(int num1, int num2)  //函数返回两个数中较大的那个数
{                            //int说明了返回值的类型
   // 局部变量声明
   int result;
 
   if (num1 > num2)
      result = num1;
   else
      result = num2;
 
   return result; 
}

int main()
{
    int a = 1, b = 2;
    int c = max(a, b);     //函数调用
    return 0;
}

1、函数声明及调用

在以上函数示例中,如果main函数出现在max函数前,就需要进行函数声明,将函数声明放在main函数前,这样才能通过计算机编译。

声明函数只需要  int max(int, int);,因为在函数声明中,参数的名称并不重要,只有参数的类型是必需的。当然也可以写全int max(int num1, int num2);

调用函数如示例中所示,用返回值接收函数调用即可,也有函数没有返回值,函数的作用可能是打印东西等,如下所示:

void print()
{
    cout<<"11111"<<endl;
}

int main()
{
    print;
    return 0;
}

2、参数的默认值

在定义函数时,可以为参数列表中后边的每一个参数指定默认值。当调用函数时,如果实际参数的值留空,则使用这个默认值。

int sum(int a , int b = 20)
{
    reutrn a+b;
}

int main()
{
    int x = 5, y = 10;
    cout<<sum(x)<<endl;      //会输出25,注意没有默认值的函数不能这样写,会少参报错
    cout<<sum(x, y)<<endl;   //会输出15
    return 0;
} 

3、Lambda函数与表达式

[capture list](parameter list) -> return type {function body}  //语法结构

captrue list: 捕获列表,用于访问外部作用域的变量,有以下几种形式

[ ]  : 不捕获任何外部变量

[x, &y] : 值捕获x,引用捕获y

[ = ] : 以值的形式捕获所有外部变量

[ & ] : 以引用的形式捕获所有外部变量

[this] : 捕获当前对象的指针

[=, &x] : 以值的形式捕获所有外部变量,但x以引用方式捕获

parameter list : 参数列表

-> return type 返回类型

{ fuction body} : 函数体

见以下示例

//无捕获,无参数的lambda
auto greet = [] {cout<<"Hello, Lambda!"<<endl; }; 
greet();

//带参数和返回值
auto add = [](int a, intb) -> int {return a+b;};
int result = add(3, 4);

//捕获外部变量
int x = 10;
auto multiply = [x](int a){return a*x;};
int result = multiply(5);

//引用捕获
int count = 0;
auto increment = [&count]{count++;};
increment();    //count会变为1

需要说明的是,在函数中如果传入的参数是引用,那么函数结束后,外部参数的值也会改变。如果传入的不是引用,那么这个参数只是个形参,哪怕在函数内部改变了这个传入参数,函数结束后外部参数也不会改变。

七、数组、字符串

1、数组

此处只是数组的简述。

//声明数组
double balance[10];

//初始化数组
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};

double balance[] =  {1000.0, 2.0, 3.4, 7.0, 50.0}; //也可以这样

int arr[5] = {1, 2}; //部分初始化,剩余元素为0,即{1, 2, 0, 0, 0}

char str[] = "hello";  //字符数组,包含'\0'结束符,长度为6

//修改与访问
balance[4] = 50.0; 

double salary = balance[0];

//多维数组
// 二维数组(3行4列)
int matrix[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

// 访问元素
int value = matrix[1][2];  // 第二行第三列(值为7)

数组名在多数情况下会隐式转换为指向首元素的指针,因此将数组作为函数参数时,不加引用也会直接在数组上修改。

2、字符串

C++的标准库提供了string类类型,现在粗略地对字符串的部分进行介绍

int main ()
{
   string str1 = "runoob";   //赋值方式
   string str2 = "google";
   string str3;
   int len ;
 
   // 复制 str1 到 str3
   str3 = str1;
 
   // 连接 str1 和 str2
   str3 = str1 + str2;
 
   // 连接后,str3 的总长度
   len = str3.size();
 
   return 0;
}

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐