C++: 宏、const、vector向量、map、智能指针、多态封装继承

C++ 编译四个过程:预处理、编译、汇编、链接

一、预处理,宏

  1. ifndef ifdef endif 分别是什么?什么作用?
    这些都是预处理命令,预处理命令不是C++语言的组成部分,是在编译之间执行的。
    C++提供三种预处理功能:宏定义、文件包含、条件编译。上面三个是条件编译的命令。
// 如果所指定的标识符已经被 #define 定义过,则只编译程序段1,否则编译程序段2. #endif 用来限制 #ifdef 命令范围
#ifdef 标识符
	程序段1
#else
	程序段2
#endif


// n代表not,作用与上述逻辑相反 
#ifndef 标识符
	程序段1
#else
	程序段2
#endif

内联函数和宏定义的区别

  1. 内联函数在编译时展开,而宏在预编译时展开
  2. 在编译的时候,内联函数直接被嵌入到目标代码中去,而宏只是一个简单的文本替换。
  3. 内联函数可以进行诸如类型安全检查、语句是否正确等编译功能,宏不具有这样的功能。
  4. 宏不是函数,而inline是函数
  5. 宏在定义时要小心处理宏参数,一般用括号括起来,否则容易出现二义性。而内联函数不会出现二义性。

C++ inline函数

inline函数一般用于比较小的,频繁调用的函数,这样可以减少函数调用带来的开销。只需要在函数返回类型前加上关键字inline,即可将函数指定为inline函数。

inline有点类似于宏定义,但是它和宏定义不同的是,宏定义只是简单的文本替换,是在预编译阶段进行的。而inline的引入正是为了取消这种复杂的宏定义的。

同其它函数不同的是,最好将inline函数定义在头文件,而不仅仅是声明,因为编译器在处理inline函数时,需要在调用点内联展开该函数,所以仅需要函数声明是不够的。

https://blog.csdn.net/u013321328/article/details/19838145

二、const, constexpr, static

  1. const关键字的作用?const和constexpr区别?const和static区别?
    const(constant):告诉编译器约束某个值不改变。在 C++ 中用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数。

被const修饰的变量变成常量,不能被再次赋值。不允许被修改。如果取它的地址再重新赋值,可能会发生意想不到的行为。在其前面再加 volatile,可以让编译器忽略 const的修饰。

// 举例:const修饰函数形参:https://blog.csdn.net/qxqxqzzz/article/details/127342899
函数参数为结构体时:地址传递减少内存(比如结构体有多个属性或成员),同时使用const修饰结构体指针形参防止误操作修改结构体属性
// void printS(student s) { // 值传递会拷贝数据占用内存
void printS(const student* s) {
    
     // 地址传递
	// s->name = 'aa' // 错误:不允许修改
}

void main {
    
    
	// printS(s); // 值传递
	printS(&s); // 地址传递,如果函数形参不加const会导致外面main函数中结构体s的属性也被修改!!
}

constexpr: 使指定的常量表达式获得在程序编译阶段计算出结果的能力,而不必等到程序运行阶段。 C++ 11 标准中,constexpr 可用于修饰普通变量、函数(包括模板函数)以及类的构造函数。

const,只读的全局变量,其值不可修改.
static,规定此全局变量只在当前模块(文件)中可见.
static const,既是只读的,又是只在当前模块中可见的.

// 修饰变量
const int a = 7;
// 撤销修饰
volatile const int  a = 7;

// 修饰指针
const int *p = 7; // 常量指针:修饰指针指向的内容:指针指向的内容为不变量
int* const p = 7; // 指针常量:修饰指针地址:指针p指向的内存地址不变,内容可变
const int* const p = 7; // const既修饰指针又修饰常量:内容和地址都不可变

常量指针,const修饰的是取*操作,所以指针指向的值不可以改,指向可以改;
指针常量,const修饰的是常量(地址),所以指针指向不可以修改,指向的值可以改

  1. const定义成员函数有什么作用?
const int& fun(int& a); //修饰返回值
int& fun(const int& a); //修饰形参
int& fun(int& a) const{
    
    } //const成员函数.const 修饰成员函数, 根本上是修饰了 this 指针。
// 任何不会修改数据成员的函数都应该声明为const 类型。如果在编写const 成员函数时,不慎修改了数据成员,或者调用了其它非const 成员函数,编译器将指出错误,这无疑会提高程序的健壮性。

https://blog.csdn.net/lz20120808/article/details/46662569
https://zhuanlan.zhihu.com/p/110159656

三、vector

  1. 传递vector作为函数参数的时候,什么时候使用引用、什么时候使用指针?传引用的时候也可以对值进行改变,如何避免?
  2. C++ Vector如何扩容?如何增加元素,有哪些方法?如何删除元素,有哪些方法?同时删除多个位置的元素有什么问题?扩容是在原地操作吗?
  3. vector的容量限制?在增加元素的时候,内存是如何变化的?

在调用push_back时,若当前容量已经不能够放入心得元素(capacity=size),那么vector会重新申请一块内存,把之前的内存里的元素拷贝到新的内存当中,然后把push_back的元素拷贝到新的内存中,最后要析构原有的vector并释放原有的内存

  1. C++数组如果不单调(但是单调性最多改变一次),怎么快速找到最大和最小值?如何遍历?如何减少时间复杂度?空间复杂度是多少?

https://www.bilibili.com/video/BV1zG4y1h71H

C++ 查找时间复杂度为O(1)的STL容器

vector和list的区别:

1)vector(顺序表-直接存储): 连续存储,动态数组,在堆上分配空间;底层实现:数组顺序内存

  • 两倍容量增长:插入新元素时,如未超过容量,则直接添加到最后,然后调整迭代器;如没有剩余空间,则重新分配原有元素个数两倍空间,然后将原空间元素复制到新空间,进行初始化,再向新空间添加新元素。最后析构释放原空间,之前迭代器失效
  • 访问:O(1),插入/删除:空间够的情况下在最后插入/删除 很快,在中间插入/删除都需要内存拷贝;空间不够的情况下在中间/最后 插入 都需要内存申请和释放,并拷贝之前数据;
  • 适用于:经常随机访问,不经常对尾节点进行插入/删除

2)list(顺序表-链式存储): 动态链表,在堆上分配空间,每插入一个元素都会分配空间,每删除一个元素都会释放空间。底层:双向链表

  • 访问:O(n) 随机访问性能差,只能快速访问头尾节点;插入/删除:O(1),适用于:经常插入删除大量数据

四、map

C++ map和 unordered_map 区别

五、智能指针

C++虚函数、虚继承、虚基类、多态、智能指针

六、多态、封装、继承

猜你喜欢

转载自blog.csdn.net/qxqxqzzz/article/details/129624789