记录以下几点:

  • const修饰符

  • static修饰符

  • C++指针和引用的区别

  • 堆和栈的区别

  • 进程和线程的区别

  • 字节序:大端法和小端法

const修饰符

  • const int m=7;:整型变量m的值为固定值7,不可改变
  • const int* p1 = &a;
    • p1指向的不可改变(简称 左定值,因为 const 位于 * 号左边)
    • *p1=b不合法,p2=&b合法
  • int* const p2 = &a;
    • p2的指向不可改变(简称右定向,const 位于 * 号右边)
    • *p2=b合法,p2=&b不合法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int a = 7;
int b = 8;

//===左定值,值(*p1)不可变 (常量const指针*)
const int* p1 = &a;
p1 = &b;//ok
//*p1 = b; // error!

//===右定向,指向(p2)不可变 (指针*常量const)
int* const p2 = &a;
//p2 = &b; // error!
*p2 = b;//ok

const int* const p3 = &a;//指向常量的指针常量

static修饰符

修饰变量、函数

函数内部定义的变量,当程序执行到它的定义处时,编译器为它在栈上分配空间,在此函数执行结束时会释放掉,这样就产生了一个问题: 如果想将函数中此变量的值保存至下一次调用时,如何实现? 最容易想到的方法是定义为全局的变量,但会破坏此变量的访问范围(使得在此函数中定义的变量,不仅仅只受此函数控制)。static 关键字则可以很好的解决这个问题。

  • static 修饰的局部变量只初始化一次,且延长了局部变量的生命周期(作用域不变),程序结束后才释放
  • static 修饰的全局变量只能在本文件中访问,不能在其它文件中访问,即便 extern 外部声明也不可以,因而其它文件中可以定义相同名字的变量,不会发生冲突
  • static 修饰的函数只能在本文件中调用,不能被其他文件调用
  • static 修饰的变量存放在全局数据区的静态变量区,包括全局静态变量和局部静态变量,初始化自动为 0

修饰类内成员

静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存

  • 静态成员可以通过双冒号来使用 <类名>::<静态成员名>,非静态成员引用必须与特定对象相对对象.成员名
  • 类的静态成员函数中不能使用类的非静态成员(因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而非静态成员在类实例化对象后才有内存空间,因而静态成员不认识后来的非静态成员)
  • 类的非静态成员函数可以调用用静态成员函数,但反之不能
  • 静态成员函数没有 this 指针(因其属于整个类)
  • 类的静态成员变量必须先初始化再使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
using namespace std;

class Point
{
public:
Point() { m_x++; }
~Point() { m_x--; }
void init()
{
output();//非静态函数可以调用用静态函数,但反之不能
}
static void output()
{
cout << m_x << endl;//static类型的m_x
}
private:
static int m_x;
};

static int x;//类外静态变量可以不初始化直接用
int Point::m_x = 0;//类的静态成员变量必须先初始化再使用
void main()
{
x++;
Point pt;
pt.init();//非静态成员只能使用pt.output()
Point::output();//静态成员也可以使用pt.output()
}

参考:https://blog.csdn.net/morewindows/article/details/6721430

C++指针和引用的区别

  • 指针是一个变量,该变量存储的是一个地址,指向内存的一个存储单元

    引用与原来的变量实质上是同一个东西,只不过是原变量的一个别名而已

  • 指针可以为空

    引用不能为空

  • 指针在初始化后,可以改变进而指向其它的变量对象

    引用只能在定义时被初始化一次,之后不可变,始终是初始化时对应的变量

  • 可以有const指针(可以有int* const p,指向int型的常量指针 ,它不能在指向别的变量)

    没有const引用(没有int& const a这种形式,引用本身即别名不可以改变,这是当然的)

  • 指针可以有多级(int **p合法)

    是引用只能是一级(int &&a是不合法的)

  • sizeof (指针)”得到的是指针本身的大小

    sizeof (引用)”得到的是所指向的变量(对象)的大小

堆和栈的区别

  • 堆空间的释放由程序员控制,容易产生memory leak

    栈空间由编译器自动管理

  • 堆的空间较大,由系统内存决定

    栈的空间有限,最大容量是系统预先规定的(1M或2M)

  • 堆频繁的new/delete造成内存空间的不连续,产成大量碎片,使程序效率降低

    栈是先进后出的结构,栈始终连续存储

  • 堆是向高地址扩展,也就是向着内存地址增加的方向

    栈是向低地址扩展,是向着内存地址减小的方向增长

  • 堆都是动态分配的,没有静态分配的堆

    栈有静态分配(由编译器完成,比如局部变量)和动态分配(由alloca函数进行分配)

  • 堆由C/C++函数库提供,机制较复杂

    栈由计算机底层提供支持

进程和线程的区别

  • 进程是资源分配的最小单位

    线程是CPU调度的最小单位

  • 进程有自己独立的地址空间,每启动一个进程,系统都会为其分配地址空间,建立数据表来维护代码段、堆栈段和数据段

    线程没有独立的地址空间,它使用相同的地址空间共享数据

  • 进程之间的通信需要以通信的方式(IPC,Inter-Process Communication)进行

    线程之间通信更方便,同一个进程下,线程共享全局变量,静态变量等数据

  • 多进程程序更安全,生命力更强,一个进程死掉不会对另一个进程造成影响(源于有独立的地址空间)

    多线程程序更不易维护,一个线程死掉,整个进程就死掉了(因为共享地址空间)

  • 进程对资源保护要求高,开销大,效率相对较低

    线程资源保护要求不高,但开销小,效率高,可频繁切换

  • CPU切换一个线程比切换进程花费小

  • 创建一个线程比进程开销小

  • 线程占用的资源要⽐进程少很多

参考:https://blog.csdn.net/wsq119/article/details/82154305

字节序:大端法和小端法

最高有效字节在最前面的方式称为大端法(先存储高位),例如假设变量x类型为int型,位于地址0x100的地方,其16进制值为0x12345678,地址范围为0x100到0x103字节。

对于大端法的机器来说(先存储高位0x12):

0x100 0x101 0x102 0x103
12 34 56 78

对于小端法的机器来说(先存储高位0x78):

0x100 0x101 0x102 0x103
78 56 34 12

参考:https://www.cnblogs.com/broglie/p/5645200.html