秋招总结(一)-C++归纳

本文详细总结了C++面试中的重点知识,涵盖STL、static关键字、sizeof与strlen的区别、struct与class、malloc与new的对比、指针与引用、右值引用的用途、extern关键字、宏定义与typedef、内联函数与define、条件编译、常引用、指针常量与常量指针、指针类型解析、数组名与指针的区别、内存管理、虚函数与纯虚函数、重载、覆盖与隐藏、构造与析构函数调用顺序、深拷贝与浅拷贝、内存对齐、编译过程、智能指针、RAII机制、C++新特性、map与unordered_map的差异、类型转换、成员函数存储、单例模式实现等方面,是C++程序员秋招必备的知识梳理。

STL相关:interview/STL at master · huihut/interview · GitHub

1.static关键字

  • 隐藏: static的全局变量和函数会对其它源文件隐藏
  • 生命周期延长:被修饰的变量位于静态存储区, 对于静态局部变量,生命周期为整个程序而并非函数作用域
  • 修饰类成员(静态成员变量和静态成员函数),静态成员变量和静态成员函数不属于任何对象,所有类实例所共有
  • 默认初始化为0,并且只会第一次调用初始化

2.sizeof和strlen区别

  • sizeof是运算符,在编译时计算; strlen是库函数,运行中调用
  • sizeof参数可以是任何数据类型或数据; strlen参数只能是字符指针且结尾是'\0'的字符串
  • sizeof值是在编译时确定,所以不能用来计算动态分配存储空间的大小
    char *p = "abcdef";//字符串
    char arr1[] = "abcdef";//字符串
    char arr2[] = {'a','b','c','d','e','f'};//6个字符。没有\0
    
    sizeof(p) = 8 ; // 指针大小为8字节(64位系统)
    sizeof(arr1) = 7; //arr1为数组名,计算数组大小 + 末尾'\0'
    sizeof(arr2) = 6; //和arr1区分,该情况末尾没有'\0'

    strlen(p) = 6;
    strlen(arr1) = 6;
    strlen(arr2) = 不确定;    //没有'\0',无法确定结束

    char *p = "abcdef0\0a";//字符串
    char arr1[] = "abcdef0\0a";//字符串
    char arr2[] = {'a','b','c','d','e','f','0','\0','a'};

    sizeof(p) = 8;  //指针大小为8字节(64位系统)
    sizeof(arr1) = 10; //'\0'算一个字符,加上末尾'\0'10个字符 
    sizeof(arr2) = 9; //没有结尾'\0'
    
    strlen(p) = 7;    //strlen均计算到'\0'之前
    strlen(arr1) = 7;
    strlen(arr2) = 7;

3.struct和class的区别

  • 结构体的默认限定符是public;类是private。

4.malloc和new的区别

  • malloc和free是标准库函数;new和delete是运算符,并且支持重载。
  • malloc返回void*指针, new返回对象类型指针
  • new/delete调用构造/析构函数,malloc/free不调用 
  • 分配内存大小: malloc必须显式指定字节数, new由编译器根据类型计算得出
  • 分配失败返回值: new默认抛出异常, malloc返回NULL
  • 处理数组:malloc计算数组大小后进行分配, new使用new[]处理     (注:delete[]会调用数组中每个元素的析构函数;delete和delete[]的区别:当delete常用类型数组(int char之类)时,delete和delete[]功能一样,但对于复杂类型,比如一个结构体数组(A k[] = new A[10]),delete k只会释放首元素,delete[]就会释放每个元素)

5.指针和引用的区别

  • 指针保存的是所指对象的地址,引用是所指对象的别名,指针需要通过解引用间接访问,而引用是直接访问;
  • 指针是具体变量,需要占用存储空间; 引用只是别名, 不占用具体存储空间;
  • 指针可以改变地址,从而改变所指的对象,而引用必须从一而终;
  • 引用在定义的时候必须初始化,而指针则不需要;
  • 指针更灵活,用的好威力无比,用的不好处处是坑,而引用用起来则安全多了,但是比较死板。

左值和右值:

有地址的变量就是左值,没有地址的字面值、临时值就是右值。

左值引用和右值引用:

左值引用大家都很熟悉,能指向左值,不能指向右值的就是左值引用

引用是变量的别名,由于右值没有地址,没法被修改,所以左值引用无法指向右值。

再看下右值引用,右值引用的标志是&&,顾名思义,右值引用专门为右值而生,可以指向右值,不能指向左值

被声明出来的左、右值引用都是左值

右值引用的目的:

  1. 移动语义:右值引用可以用于实现移动语义,这样可以避免重复构造对象,减少内存分配和复制的时间。因此,右值引用常用于函数返回值。

  2. 容器操作:右值引用可以被用于 STL 容器,如 vector、list 等,以实现快速插入和删除元素的操作。

  3. 临时对象的存储:右值引用可以用于存储临时对象,避免进行复制操作,从而提高程序效率。

  4. 返回大对象:右值引用可以用于返回大对象,避免复制和构造的操作,从而减少内存消耗。

引入右值引用,主要就是为了移动语义,C++11 std::move。移动语义就是为了减少拷贝。std::move就是将左值转为右值引用。这样就可以重载到移动构造函数了,移动构造函数将指针赋值一下就好了,不用深拷贝了,提高性能;

class Array {
public:
    ......
 
    // 优雅
    Array(Array&& temp_array) {
        data_ = temp_array.data_;
        size_ = temp_array.size_;
        // 为防止temp_array析构时delete data,提前置空其data_      
        temp_array.data_ = nullptr;
    }
     
 
public:
    int *data_;
    int size_;
};

int main(){
    Array a;
 
    // 做一些操作
    .....
     
    // 左值a,用std::move转化为右值
    Array b(std::move(a));
}
int main() {
    std::string str1 = "aacasxs";
    std::vector<std::string> vec;
     
    vec.push_back(str1); // 传统方法,copy
    vec.push_back(std::move(str1)); // 调用移动语义的push_back方法,避免拷贝,str1会失去原有值,变成空字符串
    vec.emplace_back(std::move(str1)); // emplace_back效果相同,str1会失去原有值
    vec.emplace_back("axcsddcas"); // 当然可以直接接右值
}
 
// std::vector方法定义
void push_back (const value_type& val);
void push_back (value_type&& val);
 
void emplace_back (Args&&... args);

6.extern关键字

  • extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义; 这是声明不是定义;

7.(1)define和typedef区别

  • define用于定义常量及书写复杂的内容; typedef主要用于定义类型别名
  • define作用于预处理阶段,属于文本替换; typedef是编译的一部分
  • define不检查类型; typedef检查数据类型
  • define不是语句,末尾不加分号; typedef是语句,要加分号标识结束
特别注意typedef和define在处理指针的时候的问题,如:
typedef int* pInt1;
#define pInt2 int*;

pInt1 a,b;   //等价于 int *a; int *b; 定义了两个整型指针变量
pInt2 a,b;   //等价于 int *a, b;    定义了整型指针a和整型变量b

    (2)define和内联函数(inline)区别

inline关键字的作用:<

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值