小言_互联网的博客

C/C++知识点整理

368人阅读  评论(0)

一、const

  • 修饰常量,比如 const int a = 10,说明该变量无法被修改
  • 修饰指针,包括指向常量的指针和指针常量
    指向常量的指针:const int *p = &a; 无法通过指针修改其所指变量的值(可以指向const 和 非const)
    指针常量:int *const p = &a; 不能修改指针中保存的地址
  • 常量引用,避免拷贝,同时无法通过函数对值修改void fun(const int &a,const int &b);常量引用可以用任意表达式、字面值、可类型转换的对象初始化
  • 修饰函数
    常成员函数无法修改类中的数据成员int getValue() const;

二、static

  • 修饰普通变量
    – 生命周期:main 函数之前分配,程序结束释放
    – 存储区域:全局区
  • 修饰普通函数
    – 作用范围:定义该函数的文件内才可以使用,防止与他人重名
  • 静态成员变量
    – 静态成员变量是该类的所有对象共有,只分配一次内存,该类所有对象共享访问更新
    – 存储在全局区,属于类,不属于特定对象,不占用对象内存
    – 只能在类体外初始化,且必须初始化,初始化时分配内存
    – 生命周期:编译时分配,程序结束释放
    – 访问形式:<类对象名>.<静态数据成员名> <类类型名>::<静态数据成员名>
//Example 5
#include <iostream.h>
class Myclass
{
	public:
		Myclass(int a,int b,int c);
		void GetSum();
	private:
		int a,b,c;
		static int Sum;//声明静态数据成员
};

int Myclass::Sum=0;    //定义并初始化静态数据成员

Myclass::Myclass(int a,int b,int c)
{
	this->a=a;
	this->b=b;
	this->c=c;
	Sum+=a+b+c;
}

void Myclass::GetSum()
{
	cout<<"Sum="<<Sum<<endl;
}

void main()
{
	Myclass M(1,2,3);
	M.GetSum();
	Myclass N(4,5,6);
	N.GetSum();
	M.GetSum();
}

  • 静态成员函数
    – 属于类本身,不作用与对象,不具有 this 指针,因此只能访问静态成员变量和静态成员函数
    – 出现在类体外的函数定义不能指定关键字static
    – 调用方法:成员访问操作符(.)和(->) <类名>::<静态成员函数名>(<参数表>)
//Example 6
#include <iostream>
using namespace std;

class Student{
private:
   char *name;
   int age;
   float score;
   static int num;  	//学生人数
   static float total;  //总分
public:
   Student(char *, int, float);
   void say();
   static float getAverage();  //静态成员函数,用来获得平均成绩
};

int Student::num = 0;
float Student::total = 0;

Student::Student(char *name, int age, float score)
{
   this->name = name;
   this->age = age;
   this->score = score;
   num++;
   total += score;
}

void Student::say()
{
   cout<<name<<"的年龄是 "<<age<<",成绩是 "<<score<<"(当前共"<<num<<"名学生)"<<endl;
}

float Student::getAverage()
{
   return total / num;
}

int main()
{
   (new Student("小明", 15, 90))->say();
   (new Student("李磊", 16, 80))->say();
   (new Student("张华", 16, 99))->say();
   (new Student("王康", 14, 60))->say();
   cout<<"平均成绩为 "<<Student::getAverage()<<endl;
   return 0;
}

三、this 指针

  • 非静态成员函数的隐含的特殊指针,指向调用函数的对象
  • 隐含申明为指针常量:CLassName *const this
  • 特殊:在常成员函数中,this 指针类型为指向常对象的指针常量 const ClassName *const,故常成员函数无法修改数据成员
  • 不能 &this
  • 某些情况需要显示引用 this 指针

四、inline 内敛函数

  • 相当于把函数的内容在调用函数处展开
  • 内敛函数一般比较简单,不包括循环,递归等
  • 有类内隐式内敛,类外显示内敛
  • 优点:
    – 提高程序运行速度,因为省去压栈和弹栈
    – 相比宏函数,多了安全检查和自动类型转换
  • 缺点:
    – 代码膨胀
    – inline 函数改变后需要重新编译
    – 是否内敛取决于编译器
    虚函数和内敛函数(后续更新)

五、volatile

  • volatile 关键字是类型修饰符volatile int i = 10, 它告诉编译器不要对这样的对象进行优化,每次从稳定的地址进行访问。
volatile int i=10;
int a = i;
...
// 其他代码,并未明确告诉编译器,对 i 进行过操作
int b = i;

比如上述代码,如果编译器发现两次 i 的读取过程中并未对 i 的值进行修改,会自动把上次的值放在 b 中,这样如果 i 是寄存器数据或者端口变量容易出错。
比如在定时器中断中的变量在中断外引用时容易出现此类问题,需要加volatile关键字(PPT补充)

六、assert()

  • assert() 是宏,非函数
  • 作用是如果条件返回错误,则终止程序执行
assert(p != nullptr)
  • 可以在 #include<assert.h> #include<cassert>之前定义NDEBUG来关闭
#define NDEBUG
#include <assert.h>
assert(p != null) //不起作用

七、sizeof

  • 对数组,得到整个数组所占空间大小
  • 对指针,得到指针本身所占空间大小,32位机器,指针占4个字节;64位机器,指针占8个字节

八、#pragma pack(n)

  • 自然对齐:变量的内存地址正好位于其长度的整数倍,这样有利于提高存取速度
  • 通过 #pragma pack(n)可以强制结构体、联合体及类成员变量以 n 字节对齐方式存取
struct s {
	char ch;
	int i;
};

如果 sizeof(struct s), 则结果为8,因为默认自然对齐,char 占用一个字节,int 的地址需要被 4 整除,所以需要在 char 后添加 3 个空字节,所以一共是 8 个自己。

#pragma pack(push)  // 保存对齐状态
#pragma pack(1)     // 设定为 1 字节对齐

struct s {
	char ch;
	int i;
};

#pragma pack(pop)   // 恢复对齐状态

这样可以强制结构体数据连续排列,节省资源,但速度减慢

九、位域

  • 数据在存储时占用一位或几位二进制,通常通过结构体申明
    下述代码表明申请 4 bit 的空间,由于小于 unsigned int 的空间长度,故data共占用 4 字节的空间
struct 
{
   unsigned int a:1;
   unsigned int b:1;
   unsigned int c:1;
   unsigned int d:1;
}data;
  • 位域的存储依然遵守编译器自然对齐的原则,故下述代码的中 data 占用 8 个字节
struct data
{
  unsigned a:12;  
  unsigned b:24;   
  unsigned c:6;   
};

转载:https://blog.csdn.net/Suqing_2018/article/details/104521199
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场