C++ 补充基础知识

2022/1/13 20:09:07

本文主要是介绍C++ 补充基础知识,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

注释

#if 0 ... #endif 属于条件编译,0 即为参数。
可以使用 #if 0 ... #endif 来实现注释,且可以实现嵌套,格式为:

#if 0
   code
#endif 

可以把 #if 0 改成 #if 1 来执行 code 的代码。
帮助实现程序调试,测试时使用 #if 1 来执行测试代码,发布后使用 #if 0 来屏蔽测试代码。#if 后可以是任意的条件语句。

数据类型

左值:指向内存位置的表达式(如变量),可以出现在赋值号的左边或右边。
右值:存储在内存中某些地址的数值,不能对其进行赋值,只能出现在赋值号的右边。

  • 七种基本数据类型(字节数):bool(1)、char(1)、int(4)、float(4)、double(8)、void、wchar_t(2/4) 一字节为 8 位。

  • 数据类型修饰符(字节数变化):signed、unsigned、short(/2)、long(*2) 默认情况下,int、short、long都是带符号的,即 signed

    修饰符 signed、unsigned、long 和 short 可应用于整型(int),signed 和 unsigned 可应用于字符型(char),long 可应用于双精度型(double)。
    修饰符 signed 和 unsigned 也可以作为 long 或 short 修饰符的前缀。例如:unsigned long int。

    C++ 允许使用速记符号来声明无符号短整数或无符号长整数(unsigned)。即可以不写 int,只写单词 unsigned、short 或 long,隐含 int。

  • typedef 类型声明:typedef type newname 将 type 类型声明为 newname 。

    typedef int feet;
    feet distance;		// 等同于 int distance
    
  • enum 枚举类型声明:enum 枚举名 { 标识符 [=整型常数], ...标识符 [=整型常数] } 枚举变量

    enum color { red, green, blue } c; 	// 变量 c 的类型为 color
    c = blue;	// c 被赋值为 "blue",值为 2
    // 默认情况下,第一个名称的值为 0,第二个名称的值为 1,第三个名称的值为 2,以此类推。
    
    enum color { red, green=5, blue };	// green 的值为 5, blue 的值为 6。
    // 默认情况下,每个名称都会比它前面一个名称大 1,但添加初始值前的标识符的值依然从 0 开始。
    

变量

变量定义type variable_list; 或 type variable_name = value; 变量保留它所存储值的内存位置,创建变量时会在内存中保留一些空间。变量的大小会根据编译器和所使用的电脑而有所不同。
变量声明extern type variable_list ,在头部声明变量,之后可以在代码的任意地点定义变量(声明变量可以进行编译,定义变量用于程序连接)

同样的,在函数声明时,提供一个函数名,而函数的实际定义则可以在任何地方进行。
C/C++ 代码按顺序执行,不提前在头部声明就要在函数/变量被使用的位置之前定义。

变量类型

  • 基本变量类型:bool、char、int、float、double、void、wchar_t
  • 其他变量类型:枚举、指针、数组、引用、数据结构、类等

变量作用域

  • 全局变量:所有函数外部定义的变量,在程序的整个生命周期内有效,可以被任何函数访问。
  • 局部变量:函数或代码块内声明的变量,在函数内,当局部变量与全局变量同名时,局部变量的值会覆盖全局变量的值。

当局部变量被定义时,系统不会对其初始化,您必须自行对其初始化。
定义全局变量时,系统会自动初始化为下列值:

数据类型初始化默认值
int0
char‘\0’
float0
double0
pointerNULL

常量(字面量)

常量定义:常量定义为大写字母形式。

  • #define identifier value 预处理器定义常量。

  • const type variable = value; 关键字声明指定类型的常量。

  • 基本数据类型常量:整型数字、浮点数字、字符、字符串、布尔值

    • 浮点常量可以使用小数形式或指数形式表示。

      当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。
      当使用指数形式表示时, 必须包含小数点、指数,或同时包含两者。带符号的指数是用 e 或 E 引入的。

    • 布尔常量:true、false
    • 字符常量:单引号

      如果常量以 L(仅当大写时)开头,则表示它是一个宽字符常量(例如 L’x’),此时它必须存储在 wchar_t 类型的变量中。
      否则,它就是一个窄字符常量(例如 ‘x’),此时它可以存储在 char 类型的简单变量中。

    • 字符串常量:双引号 可以使用 \ 做分隔符分行。

修饰符

数据类型修饰符

类型限定符

  • const const 类型的对象在程序执行期间不能被修改。
  • volatile 编译器不需要优化 volatile 声明的变量,程序可以直接从内存中读取变量。

    对于一般的变量编译器会对变量进行优化,将内存中的变量值放在寄存器中以加快读写效率。

  • restrict 修饰的指针是唯一一种指向它所访问的对象的方式。只有 C99 增加了新的类型限定符 restrict。

存储类说明符

存储类定义 C++ 程序中变量/函数的范围(可见性)和生命周期。这些说明符放置在它们所修饰的类型之前。

  • auto 声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。
  • register 定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 ‘&’ 运算符(因为它没有内存位置)。
  • static 指示编译器在程序的生命周期内保持局部变量的存在;当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内;当 static 用在类数据成员上时,会导致仅有一个该成员的副本被类的所有对象共享。
  • extern 通常用于当有两个或多个文件共享相同的全局变量或函数的时候,提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。

    当使用 ‘extern’ 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。
    当有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。

  • thread_local 声明的变量仅可在它在其上创建的线程上访问。 变量在创建线程时创建,并在销毁线程时销毁,每个线程都有其自己的变量副本。可以与 static 或 extern 合并使用(static thread_local std::string s;),不能用于函数声明或定义。
  • mutable仅适用于类的对象,它允许对象的成员替代常量。也就是说,mutable 成员可以通过 const 成员函数修改。

运算符

  • 算术运算符:+、-、*、/、%、++、--++B直接在变量B上+1;B++先用B运算,然后+1)
  • 关系运算符:==、!=、>、<、>=、<= 判断是否为真
  • 逻辑运算符:&&、||、! 判断是否为真
  • 位运算符:&、|、^、~、<<(左移,*2)、>>(右移,/2)
  • 赋值运算符:=、+=、-=、*=、...
  • 其他运算符在这里插入图片描述

循环

循环类型

  • while(expression) {statement;}
  • for(init ; condition ; increment) {statement;}
  • for(init ; 迭代范围) {statement;}
  • do{statement;} while(expression);

循环控制语句

  • break:终止循环或switch语句。
  • continue : 跳过循环剩余部分,开始下一次循环。
  • goto:将控制转移到被标记的语句,不建议使用 。

判断

  • if( boolean_expression) {statement;} else {statement;} 可以嵌套。
  • Exp1 ? Exp2 : Exp3;
  • switch(expression) { case constant-expression : statement; [break;] [default : statement;]}

expression 必须是一个整型或枚举类型,或者是一个 class 类型。
constant-expression 必须与 switch 中的变量具有相同的数据类型,且必须是一个常量。

函数

函数声明:return_type function_name( parameter list );
函数定义:return_type function_name( parameter list ) { body of the function }

参数调用:如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。

  • 传值调用(默认):修改函数内的形式参数对实际参数没有影响。
  • 指针调用:把参数的地址赋值给形式参数。在函数内访问实际参数,影响实际参数。
  • 引用调用:把参数的引用赋值给形式参数。在函数内访问实际参数,影响实际参数。

匿名函数( Lambda 函数):

  • 有返回值:[capture](parameters)->return-type{body}
  • 没有返回值:[capture](parameters){body}

数组

数组声明:type arrayName[arraySize];
数组初始化:type arrayName[arraySize] = {value, ..., value};

字符串

字符串实际上是使用 null 字符 \0 终止的一维字符数组。

C风格字符串声明:

char site[7] = {'R', 'U', 'N', 'O', 'O', 'B', '\0'};
// 或
char site[] = "RUNOOB";

C++ string 类

字符串函数:

strcpy(s1, s2);
// 复制字符串 s2 到字符串 s1。
strcat(s1, s2);
// 连接字符串 s2 到字符串 s1 的末尾。连接字符串也可以用 + 号。

strlen(s1);
strcmp(s1, s2);

strchr(s1, ch);
// 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。
strstr(s1, s2);
// 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。

指针

指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。

指针声明:type *varname;

varname = 变量地址
*varname = 变量地址对应的值

所有指针的值的实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,都是一样的,都是一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同。

Null指针

在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。

NULL 指针是一个定义在标准库中的值为零的常量。

指针运算

算术运算:++、--、+、-,默认的 1 是指针指向数据类型的大小

假设 ptr 是一个指向地址 1000 的整型指针,是一个 32 位的整数,让我们对该指针执行下列的算术运算:ptr++ 在执行完上述的运算之后,ptr 将指向位置 1004,因为 ptr 每增加一次,它都将指向下一个整数位置,即当前位置往后移 4个字节。
这个运算会在不影响内存位置中实际值的情况下,移动指针到下一个内存位置。如果 ptr 指向一个地址为 1000 的字符,上面的运算会导致指针指向位置 1001,因为下一个字符位置是在 1001。

关系运算符:==、<、>,如果 p1 和 p2 指向两个相关的变量,比如同一个数组中的不同元素,则可对 p1 和 p2 进行大小比较。

指针与数组

指针和数组是密切相关的。例如,一个指向数组开头的指针,可以通过使用指针的算术运算或数组索引来访问数组。

把指针运算符 * 应用到 var 上是完全可以的,但修改 var 的值是非法的。这是因为 var 是一个指向数组开头的常量,不能作为左值。由于一个数组名对应一个指针常量,只要不改变数组的值,仍然可以用指针形式的表达式。

指针数组

让数组存储指向 int 或 char 或其他数据类型的指针。

指针数组声明:type *varname[MAX];

int *ptr[MAX];
// ptr 中的每个元素,都是一个指向 int 值的指针。

用一个指向字符的指针数组来存储一个字符串列表

#include <iostream>
 
using namespace std;
const int MAX = 4;
 
int main ()
{
 	const char *names[MAX] = {
                   "Zara Ali",
                   "Hina Ali",
                   "Nuha Ali",
                   "Sara Ali",
   };
 	// names 中的元素是指向 char 类型数组的指针,即 char 类型数组的首字母地址
 	// 例如字符串数组声明: char site[] = "RUNOOB";
   for (int i = 0; i < MAX; i++)
   {
      cout << "Value of names[" << i << "] = ";
      cout << names[i] << endl;
      // *names[i] 指向首字母地址的内容,打印 char 类型数组的首字母
      // 输出字符串时,对应变量那里只写字符串第一个字符的指针。
   }
   return 0;
}

指向指针的指针(多级间接寻址)

指针的指针就是将指针的地址存放在另一个指针里面。

通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。

指针的指针声明:type **varname,当一个目标值被一个指针间接指向到另一个指针时,访问这个值需要使用两个星号运算符。

传递指针给函数

通过引用或地址传递参数,使传递的参数在调用函数中被改变。

void getSeconds(unsigned long *par);

从函数返回指针

函数返回指针到局部变量、静态变量和动态内存分配。

int * myFunction();

C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static变量。

*引用

int i = 17;
int&  r = i;		// r 是一个初始化为 i 额整型引用

不存在空引用。引用必须连接到一块合法的内存。
一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
引用必须在创建时被初始化。指针可以在任何时间被初始化。
引用不是定义一个新的变量或对象,因此内存不会为引用开辟新的空间存储这个引用。

引用作为参数

当用引用作为函数的参数时,其效果和用指针作为函数参数的效果相当。当调用函数时,函数中的形参就会被当成实参变量或对象的一个别名来使用,也就是说此时函数中对形参的各种操作实际上是对实参本身进行操作,而非简单的将实参变量或对象的值拷贝给形参。
如果参数传递的数据较大时,建议使用引用作为函数的形参,这样会提高函数的时间效率,并节省内存空间。

void swap(int& x, int& y);

引用作为返回值

数据类型——结构

结构定义:struct 语句,定义了一个包含多个成员的新的数据类型。

struct type_name {
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
.
.
} object_names;

成员访问运算符:.



这篇关于C++ 补充基础知识的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程