C++基础知识(2)

本文详细介绍了C++的基础知识,包括内存分区、指针与引用的区别、内存对齐及其规则、内联函数与宏定义的对比、哈希表和一致性哈希、extern "C"的作用、成员初始化列表的使用、C++中的左值和右值引用、Map与unordered_map、Set与unordered_set的异同、友元函数与转换函数、成员函数的重载、覆盖和隐藏、类的动态内存分配、大端小端存储模式以及代码重用策略等。此外,还讨论了C++与Python的区别、创建共享常量的方法以及智能指针的使用,如shared_ptr、unique_ptr和weak_ptr。
摘要由CSDN通过智能技术生成

一 C++内存分区

二 指针&引用

指针和引用的区别:

(1)指针和引用都是一种内存地址的概念,但是指针是一个实体,引用是一个别名。

(2)指针指向一块内存,内容是所指内存的地址,指针的内容是可以改变的,有const与非const之分,甚至可以为空。sizeof得到的是指针类型的大小。

(3)引用只是一个内存的别名,引用必须且只可以在定义时被绑定到一块内存上,后续不可以更改,也不为空,没有const与非const之分,sizeof得到的是它所代表对象的大小。

(4)在参数传递时,指针必须解除引用才可以对对象进行操作,而直接对引用进行的修改都会作用到引用所指对象上。

一.指针
1.指向的是地址,可改变
2.可以为空
3.占用空间
4.sizeof是指针大小

二.引用
1.代表别名,与对象绑定后,就不可改变
2.定义的时候必须初始化
3.不占用空间
4.sizeof是所引用的对象大小

三 内存对齐

内存对齐的理由

(1)经过内存对齐之后,CPU 的内存访问速度大大提升。因为 CPU 把内存当成是一块一块的,块的大小可以是 2,4,8,16 个字节。在读取内存的时候是一块一块进行读取。比如说 CPU 要读取一个 4 个字节的数据到寄存器中(假设内存读取粒度是 4),如果数据是从 0 字节开始的,那么直接将 0-3 四个字节完全读取到寄存器中进行处理即可。如果数据是从 1 字节开始的,就首先要将前 4 个字节读取到寄存器,并再次读取 4-7 个字节数据进入寄存器,接着把 0 字节,5,6,7 字节的数据剔除,最后合并 1,2,3,4 字节的数据进入寄存器,所以说,当内存没有对齐时,寄存器进行了很多额外的操作,大大降低了 CPU 的性能。

(2)有的 CPU 遇到未进行内存对齐的处理直接拒绝处理,不是所有的硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。所以内存对齐还有利于平台移植。

在 Linux 中,默认对齐参数为4。

内存对齐的规则

简单来说:数据项只能存储在地址是数据项大小的整数倍的内存位置上。

(1)对于结构体的各个成员,第一个成员的偏移量是0,排列在后面的成员其当前偏移量必须是当前成员类型的整数倍。

(2)结构体内所有数据成员各自内存对齐后,结构体本身还要进行一次内存对齐,保证整个结构体占用内存大小是结构体内最大数据成员的最小整数倍。

C语言和C++中空类和空结构体的大小 。

在C++中规定了空结构体和空类的内存所占大小为1字节,因为c++中规定,任何不同的对象不能拥有相同的内存地址。

而在C语言中,空的结构体在内存中所占大小为0。

四 内联函数与宏定义

宏定义和内联函数的区别

1. 宏定义不是函数,但是使用起来像函数。预处理器用复制宏代码的方式代替函数的调用,省去了函数压栈退栈过程,提高了效率。

    内联函数本质上是一个函数,内联函数一般用于函数体的代码比较简单的函数,不能包含复杂的控制语句,while、switch,并且内联函数本身不能直接调用自身。如果内联函数的函数体过大,编译器会自动的把这个内联函数变成普通函数。

2. 宏定义是在预编译的时候把所有的宏名用宏体来替换,简单的说就是字符串替换

    内联函数则是在编译的时候进行代码插入,编译器会在每处调用内联函数的地方直接把内联函数的内容展开,这样可以省去函数的调用的开销,提高效率

3. 宏定义是没有类型检查的,无论对还是错都是直接替换

    内联函数在编译的时候会进行类型的检查,内联函数满足函数的性质,比如有返回值、参数列表等

4. 宏定义和内联函数使用的时候都是进行代码展开。不同的是宏定义是在预编译的时候把所有的宏名替换,内联函数则是在编译阶段把所有调用内联函数的地方把内联函数插入。这样可以省去函数压栈退栈,提高了效率

来自 <内联函数与宏定义 - mximo - 博客园>

使用宏和内联函数都可以节省在函数调用方面所带来的时间和空间开销。二者都采用了空间换时间的方式,在其调用处进行展开:

(1)  在预编译时期,宏定义在调用处执行字符串的原样替换。在编译时期,内联函数在调用处展开,同时进行参数类型检查。

(2)  内联函数首先是函数,可以像调用普通函数一样调用内联函数。而宏定义往往需要添加很多括号防止歧义,编写更加复杂。

(3)  内联函数可以作为某个类的成员函数,这样可以使用类的保护成员和私有成员。而当一个表达式涉及到类保护成员或私有成员时,宏就不能实现了(无法将this指针放在合适位置)。

可以用内联函数完全替代宏。

在编写内联函数时,函数体应该短小而简洁,不应该包含循环等较复杂结构,否则编译器不会将其当作内联函数看待,而是把它决议成为一个静态函数。

有些编译器甚至会优化内联函数,通常为避免一些不必要拷贝和构造,提高工作效率。

频繁的调用内联函数和宏定义容易造成代码膨胀,消耗更大的内存而造成过多的换页操作。

原文链接:

内联函数和宏定义的区别_ 我有一个梦想-CSDN博客

宏定义:

#define MAX(a,b) (a>=b?a:b)

#define Sq(a) (a)*(a)

五 哈希

哈希表/哈希冲突解决方式

哈希散列_带你去网吧里偷耳机的博客-CSDN博客_哈希函数散列地址

一致性哈希:

一致性哈希(hash)算法 - 明志健致远 - 博客园

六 Extern C

extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。

由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。

extern是编程语言中的一种属性,它表征了变量、函数等类型的作用域(可见性)属性,是编程语言中的关键字。当进行编译时,该关键字告诉编译器它所声明的函数和变量等可以在本模块或者文件以及其他模块或文件中使用。通常,程序员都只是在“*.h”(头文件)中使用该关键字以限定变量或函数等类型的属性,然后在其他模块或本模块中使用。

extern "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern "C"来说明。

七 C++成员初始化列表

成员初始化列表的概念,为什么用成员初始化列表会快一些(性能优势)?

 1)概念:

在类的构造函数中,不再函数体内对变量赋值,而在参数列表后,跟 一个冒号和初始化列表。

 2)使用初始化列表的必要性:

(1) 如果类中有const 成员或引用类型的成员,由 于const对象和引用类型都只能初始化,不支持赋值,所以这种情况必需使用初 始化列表;

(2)类中含有其它类作为成员,作为成员的类将赋值操作禁止了,也必 需用初始化列表;

 3)使用初始化列表的性能优势:

从上面的必要性可以看出适用更多的情况。另 外,如果类中包含其它类,在进入构造函数时,实际上已经构造了其它类的临时 对象,然后在构造函数中再进行赋值操作,完成完整的构造函数。但如果使用初 始化列表,则可以省去构造临时对象,直接完成初始化工作,效率更高。

 4)注意事项:

(1)构造对象的顺序按照成员属性声明的顺序,而不是成员初始化 列表的顺序;

(2) 静态对象只构造一次;

(3) 所有全局对象在main()函数之前被构造, 且一般按照声明的顺序构造。

参考博文 C++必须使用【初始化列表】初始化数据成员的三种情况_小凡的专栏-CSDN博客_成员初始化列表

八 C++接受不定长数组输入

C++编程中,可能会出现输入为不定长的数组数据。

例如:输入为一些整数,整数之间以空格隔开。

本来以为这个可以解决,但是很可惜,输入以空格隔开的几个整数后,再输入换行,还是在等着输入。。。。

首先读入一行字符串,也即将键入的以空格为分隔符的一行字符串数字存入一个string对象中,然后用isstringstream进行分割,分割的整数存在变量istr中,然后循环istr>>a,依次输出。

getline仅以换行作为结束符。

使用的时候注意添加头文件#include <sstream>和配合使用的#include <string>。

九 左值/右值/左值引用/右值引用/移动语义

引用必须在声明的时候被初始化。

左值/右值

按字面意思,通俗地说。以赋值符号 = 为界,= 左边的就是左值,= 右边就是右值。

更深一层,可以将 L-value 的 L, 理解成 Location,表示定位,地址。将 R-value 的 R 理解成 Read,表示读取数据。

左值参数是可以被引用的数据对象,如变量,数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值