玩命加载中 . . .

关键字与运算符


关键字与运算符

指针与引用

  1. 指针存放某个对象的地址,其本身就是变量(命了名的对象),本身就有地址,所以可以有指向指针的指针;可变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变
  2. 引用就是变量的别名,从一而终,不可变,必须初始化
  3. 不存在指向空值的引用,但是存在指向空值的指针

define 和 typedef 的区别

define:

  1. 只是简单的字符串替换,没有类型检查
  2. 是在编译的预处理阶段起作用
  3. 可以用来防止头文件重复引用
  4. 不分配内存,给出的是立即数,有多少次使用就进行多少次替换

typedef:

  1. 有对应的数据类型,是要进行判断的
  2. 是在编译、运行的时候起作用
  3. 在静态存储区中分配空间,在程序运行过程中内存中只有一个拷贝

define 和 inline 的区别

1、define:定义预编译时处理的宏,只是简单的字符串替换,无类型检查,不安全。
2、inline:先将内联函数编译完成的函数体直接插入被调用的地方,减少了压栈,跳转和返回的操作。没有普通函数调用时的额外开销
内联函数是一种特殊的函数,会进行类型检查
对编译器的一种请求,编译器有可能拒绝这种请求

C++中inline编译限制

  1. 不能存在任何形式的循环语句
  2. 不能存在过多的条件判断语句
  3. 函数体不能过于庞大
  4. 内联函数声明必须在调用语句之前

override 和 overload

1、override是重写(覆盖)了一个方法
以实现不同的功能,一般是用于子类在继承父类时,重写父类方法
规则:

  1. 重写方法的参数列表,返回值,所抛出的异常与被重写方法一致
  2. 被重写的方法不能为private
  3. 静态方法不能被重写为非静态的方法
  4. 重写方法的访问修饰符一定要大于被重写方法的访问修饰符(public>protected>default>private)

2、overload是重载,这些方法的名称相同而参数形式不同
一个方法有不同的版本,存在于一个类中。
规则:

  1. 不能通过访问权限、返回类型、抛出的异常进行重载
  2. 参数列表可以是不同的参数类型,不同的参数个数,不同的参数顺序(参数列表必须不一样)
  3. 方法的异常类型和数目不会对重载造成影响

new 和 malloc

1、new内存分配失败时,会抛出bad_alloc异常,它不会返回NULL;malloc分配内存失败时返回NULL
2、使用new操作符申请内存分配时无须指定内存块的大小,而malloc则需要显式地指出所需内存的尺寸
3、opeartor new/operator delete可以被重载,而malloc/free并不允许重载
4、new/delete会调用对象的构造函数/析构函数以完成对象的构造/析构。而malloc则不会
5、malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符
6、new操作符从自由存储区上为对象动态分配内存空间,而malloc函数从堆上动态分配内存

constexpr 和 const

const 表示“只读”的语义,constexpr 表示“常量”的语义
constexpr 只能定义编译期常量而 const 可以定义编译期常量也可以定义运行期常量。
你将一个成员函数标记为constexpr,则顺带也将它标记为了const。如果你将一个变量标记为constexpr,则同样它是const的。但相反并不成立,一个const的变量或函数,并不是constexpr的

constexpr变量

复杂系统中很难分辨一个初始值是不是常量表达式,可以将变量声明为constexpr类型,由编译器来验证变量的值是否是一个常量表达式。
必须使用常量初始化

constexpr int n = 20;
constexpr int m = n + 1;
static constexpr int MOD = 1000000007;

如果constexpr声明中定义了一个指针,constexpr仅对指针有效,和所指对象无关

constexpr int *p = nullptr; // 常量指针,顶层const
const int *q = nullptr; // 指向常量的指针,底层const
int* const q = nullptr; // const常量指针,顶层const

constexpr函数

constexpr函数是指能用于常量表达式的函数
函数的返回类型和所有形参类型都是字面值类型,函数体有且只有一条return语句

constexpr int new() { return 42; }

为了可以在编译过程展开,constexpr函数被隐式转换成了内联函数。
constexpr和内联函数可以在程序中多次定义,一般定义在头文件

constexpr 构造函数

构造函数不能说const,但字⾯值常量类的构造函数可以是constexpr
constexpr构造函数必须有一个空的函数体,即所有成员变量的初始化都放到初始化列表中。对象调用的成员函数必须使用 constexpr 修饰

const

指针常量: const int* ptr = new int(2); 不能改变对象的值
常量指针: int* const cptr = new int(2); 不能改变指向

左定值,右定向:指的是const*的左还是右边

顶层const:指针本身是常量
底层const:指针所指的对象是常量
若要修改const修饰的变量的值,需要加上关键字volatile
若想要修改const成员函数中某些与类状态无关的数据成员,可以使用mutable关键字来修饰这个数据成员

const和static成员

关键字 修饰常量 修饰成员变量 修饰成员函数
const 超出其作用域后空间会被释放,在定义时必须初始化,之后无法更改。
const形参可以接受const和非const类型的实参
只在某个对象的生命周期内是常量,而对整个对象而言是可变的不能赋值
不能在类外定义,只能通过构造函数初始化列表进行初始化【因为不同的对象对其const数据成员的值可以不同,所以不能在类中声明时初始化】
防止成员函数修改对象的内容『不能修改成员变量的值,但是可以访问』
const对象不可以调用非const的函数,但是非const的对象可以
static 在函数执行后不会释放其存储空间 只能在类定义体内部声明,外部初始化,且不加static 1.作为类作用域的全局函数『不能访问和调用非静态数据成员和调用非静态成员函数』
2.没有this指针『不能直接存取类的非静态成员,调用非静态成员函数』
3.不能声明为virtual

conststatic不能同时修饰成员函数,因为静态成员函数不含有this指针,即不能实例化,而const成员函数必须具体到某一实例

constexpr的好处

  1. 为一些不能修改数据提供保障,写成变量则就有被意外修改的风险。
  2. 有些场景,编译器可以在编译期对constexpr的代码进行优化,提高效率。
  3. 相比宏来说,没有额外的开销,但更安全可靠

volatile

与const绝对对立的,是类型修饰符。影响编译器编译的结果,用该关键字声明的变量表示该变量随时可能发生变化,与该变量有关的运算,不要进行编译优化;会从内存中重新装载内容,而不是直接从寄存器拷贝内容

作用:指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值,保证对特殊地址的稳定访问

使用场合:在中断服务程序和cpu相关寄存器的定义

for (volatile int i = 0; i < 10000; i++);   // 会执行,不会被优化掉

extern

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

static

实现多个对象之间的数据共享+隐藏,并且使用静态成员还不会破坏隐藏原则;默认初始化为0

前置++与后置++

self& operator++() {    // 前置
    node = (linktype)((node).next);
    return *this;
}

const self operator++(int) {    // 后置
    self tmp = *this;
    ++*this;
    return tmp
}

为了区分前后置,重载函数是以参数类型来区分,在调用的时候,编译器默默给int指定为0


1、某文件中定义的静态全局变量(或称静态外部变量),其作用域是本文件。静态全局变量只在定义该变量的源文件内有效,在同一源程序的其他源文件中不能使用它

2、如何判断一段程序是由C编译器还是由C++编译器编译的

#ifdef __cplusplus
    cout << "C++";
#else
    cout << "C";
#endif

3、C++函数中值的传递方式有:值传递、指针传递和引用传递

4、C和C++有什么不同?

  1. 从机制上,C是面向过程的,C++是面向对象的,提供了类。C也可以编写面向对象的程序,但是C++编写面向对象的程序比C容易
  2. 从使用场景:C适合要求代码体积小,效率高的场景,如嵌入式;C++适合更上层的复杂的场景;Linux的核心大部分是C写的,因为它是系统软件,效率要求极高

5、内联函数在编译时要做参数类型检查,这是内联函数跟宏相比的优势

6、内存的分配

(1) 静态存储区,程序编译时就已经分配好了,这块内存在程序的整个运行期间都存在。例如全局变量
(2) 在栈上创建,在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元被自动释放
(3) 在堆上分配,也称动态内存分配,程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责用free和delete释放内存

7、全局变量和局部变量区别

  1. 生命周期不同:全局变量随主程序开始而创建,随主程序结束而销毁;局部变量在局部函数内部或者局部循环体内部存在,退出就不存在了
  2. 全局变量分配在全局数据段,局部变量则分配在堆栈里面

文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录