C++常用关键字总结

C++98的关键字: 

C++常用关键字总结_第1张图片

单个详解:(从a~z排序解释)

  • asm

asm:是语句分隔符,后面大括号其中放汇编指令。

_asm {
    MOV a,1
    MOV b,2
    ADD c,a,b
}
  • auto

这里只说明C++11的新定义。

C++11中,标准委员会赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

int a = 10; 
auto b = a;     //得到b int类型
auto c = 'a';    //得到c char类型

注意:使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类 型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变 量实际的类型。

auto一些应用场景:

  • 在引用、指针的使用

用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&

int x = 10;    
auto a = &x;    //auto是:int*
auto* b = &x;    //auto是:int
auto& c = x;    //auto是int
//用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
  • 在同一行定义多个变量

 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个 类型进行推导,然后用推导出来的类型定义其他变量。

auto a = 1, b = 2;     
auto c = 3, d = 4.0;  // 该行代码会编译失败,因为c和d的初始化表达式类型不同
  • auto在实际中常见的优势用法就是:范围for循环,还有lambda表达式等进行配合使用。 

范围for的语法:

for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

旧式的遍历数组方式:

void Test() { 
    int array[] = { 1, 2, 3, 4, 5 }; 
    for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)     
        array[i] *= 2;
 
    for (int* p = array; p < array + sizeof(array)/ sizeof(array[0]); ++p)     
        cout << *p << endl; 
}

利用auto关键字:

注意:与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。 

void Test() { 
    int array[] = { 1, 2, 3, 4, 5 }; 
    for(auto& e : array)     
        e *= 2;
 
    for(auto e : array)     
        cout << e << " ";
    return 0; 
}

使用条件:for循环迭代的范围必须是确定的;迭代的对象要实现++和==的操作。

auto不能用的场景:

  1. auto不能作为函数的参数 
  2. auto不能直接用来声明数组
  3. 实例化模板时不能使用auto作为模板参数
  • bool,ture,false

bool类型取值范围仅有两个值:true和false。在做逻辑运算时,默认非零即为ture。

  • break,continue,goto

break 直接跳出当前的循环,从当前循环外面开始执行,忽略循环体中任何其他语句和循环条件测试。他只能跳出一层循环,如果你的循环是嵌套循环,那么你需要按照你嵌套的层次,逐步使用break来跳出。

continue也是终止当前的循环过程,但他并不跳出循环,而是继续往下判断循环条件执行语句。他只能结束循环中的一次过程,但不能终止循环继续进行。  

goto用于无条件跳转到函数内的标号。程序较少使用goto,更多使用循环代替,因为代码的可读性,结构性都会变差。

  • case,default,switch

分支语句中。switch是分支语句的起始位置,根据switch条件跳转到case标号,不满足的跳到defalut标记的分支上。

  • catch,throw,try

异常处理中使用。try指定try块的起始,try块后的catch可以捕获异常。异常由throw抛出。throw在函数中还表示动态异常规范,但在C++11中被标记为过时(由noexcept部分取代)。

  • char,wchar_t

表示字符型和宽字符型这些整数类型(属于基本类型),但一般只专用于表示字符

  • struct,class,union

用于类型声明。class是一般的类类型。struct在C++中是特殊的类类型,声明中仅默认隐式成员和基类访问限定与class不同(struct是public,class是private)。

union是联合体类型。满足特定条件类类型——POD struct或POD union可以和中的struct和union对应兼容。

class还有个用途是在模版类型声明中作为表示模版类型参数或模版模版参数的语法的必要组成部分。也可被typename代替。

  • do,for,while

循环语句的组成部分。C++支持do-while循环、for循环和while循环。C++11新增了范围for循环,用分隔声明的对象和指定循环的范围。(auto关键字的使用)

  • const、volatile

const修饰非成员变量:

 const全局变量:编译器不允许对const全局变量的改动。const表示只读类型(指定类型安全性,保护对象不被意外修改)

const局部变量:

C++常用关键字总结_第2张图片 图片来源-const部分参考博客

解决这个问题的方法是volatile关键字。

volatile关键字使得程序每次直接去内存中读取变量值而不是读寄存器值,这个作用在解决一些不是程序而是由于别的原因修改了变量值时非常有用。

volatile指定被修饰的对象类型的读操作是副作用(因此读取不能被随便优化合并,适合映射I/O寄存器等)。

volatile:

  • a、当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中,以后再取变量值时,就直接从寄存器中取值。
  • b、优化器在用到volatile变量时必须每次都小心地重新读取这个变量的值,而不是使用保存到寄存器里的备份。
  • c、volatile适用于多线程应用中被几个任务共享的变量。

cosnt修饰指针:

const修饰指针,涉及到两个很重要的概念,顶层const底层cosnt。

顶层const(top-level const):指针本身是个常量

底层const(low-level const):指针指向对象是一个常量

int a = 1;
int b = 2;

const int* p1 = &a;
int* const p2 = &a;

根据从内到外,由近到远读符号的规则:

p1依次解读为:p1是个指针(*),指向一个int型对象(int),该对象是个常量(const)。 因此这是一个底层cosnt。

p2依次解读为:p2是个常量(const),p2是个指针(*),指向一个int对象(int)。 因此这是一个顶层const。

const修饰函数参数

const修饰参数是为了防止函数体内可能会修改参数原始对象。因此,有三种情况可讨论:

函数参数为值传递:值传递(pass-by-value)是传递一份参数的拷贝给函数,因此不论函数体代码如何运行,也只会修改拷贝而无法修改原始对象,这种情况不需要将参数声明为const。

函数参数为指针:指针传递(pass-by-pointer)只会进行浅拷贝,拷贝一份指针给函数,而不会拷贝一份原始对象。因此,给指针参数加上顶层const可以防止指针指向被篡改,加上底层const可以防止指向对象被篡改。

函数参数为引用:引用传递(pass-by-reference)有一个很重要的作用,由于引用就是对象的一个别名,因此不需要拷贝对象,减小了开销。这同时也导致可以通过修改引用直接修改原始对象(毕竟引用和原始对象其实是同一个东西),因此,大多数时候,推荐函数参数设置为pass-by-reference-to-const。给引用加上底层const,既可以减小拷贝开销,又可以防止修改底层所引用的对象。

const成员函数

const实施与成员函数上,只要是防止成员函数修改类对象的内容。良好的类接口设计应该确保如果一个成员函数功能上不需要修改对象的内容,该成员函数应该加上const修饰。

如果const成员函数想修改成员变量值,可以用mutable修饰目标成员变量。

如果一个类对象为const 对象,语义上说明该对象的值不可改变,因此该const对象只能调用const成员函数,因为非const成员函数不能保证不修改对象值,编译器会禁止这种会造成隐患的行为。

mutable

mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。

  • new,delete

 new、delete属于操作符。new表示向内存申请一段新的空间,申请失败会抛出异常。new会先调用operator new函数,再在operator new函数里调用malloc函数分配空间,然后再调构造函数。

delete不仅会清理资源,还会释放空间。delete先调用析构函数,其次调用operator delete函数,最后在operator delete函数里面调用free函数。

malloc申请内存失败会返回空。free只是清理了资源,并没有释放空间。

  • if,else
  • 数值类型,如 int、double、float、short、long、signed、unsigned

这里要说明的是:char:1字节;short:3字节;int:4字节;long:4字节;float:4字节;double:8字节

  •  enum

构成枚举类型名的关键字。

  • export

使用该关键字可实现模板函数的外部调用。对模板类型,可以在头文件中声明模板类和模板函数;在代码文件中,使用关键字export来定义具体的模板类对象和模板函数;然后在其他用户代码文件中,包含声明头文件后,就可以使用该这些对象和函数。

  • extern

当出现extern “C”时,表示 extern “C”之后的代码按照C语言的规则去编译;当extern修饰变量或函数时,表示其具有外部链接属性,即其既可以在本模块中使用也可以在其他模块中使用。 

  •  friend

友元。使其不受访问权限控制的限制。例如,在1个类中,私有变量外部是不能直接访问的。可是假如另外1个类或函数要访问本类的1个私有变量时,可以把这个函数或类声明为本类的友元函数或友元类。这样他们就可以直接访问本类的私有变量。

  • inline

 内联函数,在编译时将所调用的函数代码展开直接嵌入到主调函数中。这只是一种建议,编译器可以不接受;有循环、递归、代码过长的时候就不会进行展开。

  • namespace
  • public、protected、private

这三个都为权限修饰符。public为公有的,访问不受限制;protected为保护的,只能在本类和友元中访问;private为私有的,只能在本类、派生类和友元中访问。 

  • register

提示编译器尽可能把变量存入到CPU内部寄存器中。 

  • return
  • static

可修饰变量(静态全局变量,静态局部变量),也可以修饰函数和类中的成员函数。static修饰的变量的周期为整个函数的生命周期。具有静态生存期的变量,只在函数第一次调用时进行初始化,在没有显示初始化的情况下,系统把他们初始化为0。

  1. 修饰局部变量:static修饰的静态局部变量只执行一次,而且延长了局部变量的生命周期,随程序的结束而结束。
  2. 修饰全局变量:被static修饰的全局变量只能在本文件中访问,不能再其它文件中访问。
  3. 修饰函数:修饰的函数只能在本文件中调用,不能被其它文件调用。

static修饰的局部变量存放在全局数据区的静态变量区,初始化的时候自动初始化为0;

  • 不想被释放的时候,可以使用static修饰。比如修饰函数中存放栈空间的数组,如果不想让这个数组在函数调用时结束则可用static修饰。
  • 考虑到数据安全性(当程序想要使用全局变量的时候应该考虑使用static)

static修饰静态数据成员

  1. 静态数据成员可以实现多个对象之间的数据共享,它是类的所有对象的共享成员,它在内存中只占一份空间,如果改变它的值,则各对象中这个数据成员的值都被改变。
  2. 静态数据成员是在程序开始运行时被分配空间,到程序结束之后才释放,只要类中指定了静态数据成员,即使不定义对象,也会为静态数据成员分配空间。
  3. 静态数据成员可以被初始化,但只能在类体外进行初始化,若为静态数据成员赋初值,则编译器会自动为其初始化为0.
  4. 静态数据成员既可以通过对象名引用,也可以通过类名引用。

static修饰静态成员函数

  1. 静态成员函数和静态数据成员一样,他们都属于类的静态成员,而不是对象成员。
  2. 非静态成员函数有this指针,而静态成员函数没有this指针。
  3. 静态成员函数主要用来访问静态数据成员而不能访问非静态成员。
  • sizeof 

这里说明 sizeof 和 strlen 的区别。

strlen是用来计算字符串的长度,遇到第一个NULL('\0')为止,不包括‘\0’。

sizeof是用来计算变量或者对象、类型所占字节的多少。

char s1[] = "hello";
char* s2 = "hello";
char s3[10] = "hello";

sizeof(s1) = 5 
strlen(s1) = 5

sizeof(s2) = 4  (在32位系统是4,在64系统是8)
strlen(s2) = 5

sizeof(s3) = 1*10
strlen(s3) = 5


int a[50];         
//sizeof(a)=4*50=200;  //求数组所占的空间大小

int *a = new int[50]; 
// sizeof(a)=4; a为一个指针,sizeof(a)是求指针的大小,在32位系统中,当然是占4个字节

    总结如下,当参数分别如下时,sizeof返回的值表示的含义如下:

  • 数组——编译时分配的数组空间大小;
  • 指针——存储该指针所用的空间大小(在32位系统是4,在64系统是8);
  • 类型——该类型所占的空间大小;
  • 对象——对象的实际占用空间大小;
  • 函数——函数的返回类型所占的空间大小。函数的返回类型不能是void

strlen是个函数,并且所传入的参数必须是char*,发生在运行时刻。

sizeof只关心这块内存的大小,不关心这块内存存放了什么数据,strlen只关心这块内存存放的数据,不关心这块内存的大小,直到遇到第一个NULL为止

char* s = "0123456789";
sizeof(s);     //结果 4    ===》s是指向字符串常量的字符指针
sizeof(*s);    //结果 1    ===》*s是第一个字符
strlen(s);     //结果 10   ===》有10个字符,strlen是个函数内部实现是用一个循环计算到\0为止之前
strlen(*s);     //结果 10   ===》错误


char s[] = "0123456789";
sizeof(s);     //结果 11   ===》s是数组,计算到\0位置,因此是10+1
strlen(s);     //结果 10   ===》有10个字符,strlen是个函数内部实现是用一个循环计算到\0为止之前
sizeof(*s);    //结果 1    ===》*s是第一个字符

char s[100] = "0123456789";
sizeof(s);     //结果是100 ===》s表示在内存中的大小 100×1
strlen(s);     //结果是10  ===》strlen是个函数内部实现是用一个循环计算到\0为止之前

int s[100] = "0123456789";
sizeof(s);     //结果 400  ===》s表示再内存中的大小 100×4
strlen(s);     //错误      ===》strlen的参数只能是char* 且必须是以‘\0‘结尾的

char q[]="abc";
char p[]="a\n";
sizeof(q),sizeof(p),strlen(q),strlen(p);\\结果是 4 3 3 2

char p[] = {'a','b','c','d','e','f','g','h'};
char q[] = {'a','b','c','d,'\0','e','f','g'};
sizeof(p);     //结果是8 ===》p表示在内存中的大小 8×1
strlen(p);     //为一个随机值,结果与编译器有关,不同编译器结果一般不同
sizeof(q);     //结果是8 ===》p表示在内存中的大小 8×1
strlen(q);     //结果为4 ===》存在'\0',遇到'\0'计算停止。

本部分参考博文:参考一、参考二

struct Stu
{
int i;
int j;
char k;
};
Stu stu;
printf("%d\n",sizeof(Stu));  //结果 12  ===》内存补齐
printf("%d\n",sizeof(stu));;  //结果 12  ===》内存补齐  
  • template

声明一个模板,模板函数,模板类等。模板的特化。

  •   virtual

声明虚基类,虚函数。虚函数=0时,则为纯虚函数,纯虚函数所在的类称为抽象类。 为了就是实现多态。

  •  typedef
  • this
  • typename

告诉编译器把一个特殊的名字解释为一个类型。

  • using
  • void
  • *_cast(四种类型转换)

 即 const_cast、dynamic_cast、reinterpret_cast、static_cast。

  • C++类型风格来性转换。const_cast删除const变量的属性,方便赋值;
  • dynamic_cast用于将一个父类对象的指针转换为子类对象的指针或引用;
  • reinterpret_cast将一种类型转换为另一种不同的类型;
  • static_cast用于静态转换,任何转换都可以用它,但他不能用于两个不相关的类型转换。

你可能感兴趣的:(C++)