另外还有 long double 不少于double 不低于double
注意:
在VS和Linux中 long double占用的内存空间分别是8和16个字节
c++11原始字面量
void的关键字
在C++中,void表示为无类型 主要有3个用途
1、函数的返回值用void 表示函数没有返回值
2、函数的参数填void,表示函数不需要参数(或者大多数都是让参数列表空着)
3、函数的形参用void* 表示接受任意数据类型的指针。
C++内存模型
堆和栈的主要区别:
1 管理方式不同:栈是系统自动管理的,在出作用域时,将自动被释放;堆需要手动释放,若程序中不释放,程序结束时由操作系统回收。
2 空间大小不同:堆内存的大小受限于物理内存空间;而栈空间小的可怜,一般只有8M(可以修改系统参数)
3 分配方式不同:堆是动态分配的;栈有静态分配和动态分配(都是自动释放)。
4 分配效率不同:栈是系统提供的数据结构,计算机在底层提供了对栈的支持,进栈和出栈有专门的指令,效率比较高;堆由C++函数库提供的。
5 是否产生碎片:对于栈来说,进栈和出栈都是有着严格的顺序(先进后出),不会产生碎片;而堆频繁的分配和释放,会造成内存空间的不连续,容易产生碎片,太多的碎片会导致性能的下降。
6 增长方向不同:栈向下增长,以降序分配内存地址;堆向上增长,以升序分配内存地址。
动态分配内存new和delete
意:
1 动态分配出来的内存没有变量名,只能通过指向它的指针来操作内存中的数据
2 如果动态分配的内存不用了,必须用delete释放它,否则有可能用尽系统的内存,最终导致程序崩溃,也可能引起系统崩溃。
3 动态分配的内存生命周期与程序相同,程序退出时,如果没有释放,系统将自动回收。
4 就算指针的作用域已失效,所指向的内存也不会释放。(因为可以多个指针指向同一个内存,如果其中一个指针失效而释放内存,别的指针就会发生错误)
5 用指针跟踪已分配的内存时,不能跟丢
二级指针
函数指针
#include "iostream"
using namespace std;
void func(int no, string str)
{
cout << "hello" << no << str << endl;
}
void test()
{
int a;
char b;
cout << "a=" << (void *)&a << endl;
cout << "b=" << (void *)&b << endl;
//函数指针
//普通调用
int no = 3;
string msg = "你好";
func(no, msg);
//函数指针调用
void (*f)(int, string); //声明函数的函数指针
f = func; //对函数指针赋值,语法是 函数指针名 = 函数名
f(no, msg); //用函数指针名调用函数 C++
(*f)(no, msg); //用函数指针名调用函数 C
}
void zs()
{
cout << "zs" << endl;
}
void ls()
{
cout << "ls" << endl;
}
void show(void (*pf)())
{
cout << "hello" << endl;
pf();
cout << "world" << endl;
}
void test2()
{
show(zs);
}
int sum(int a, int b)
{
return a + b;
}
void show2(int (*pf)(int, int), int a, int b)
{
cout << "show2 start" << endl;
int sum = pf(a, b);
cout << "sum=" << sum << endl;
cout << "show2 end" << endl;
}
void test3()
{
show2(sum, 2, 3);
}
int main()
{
test();
test2();
test3();
return 0;
}
a=0x61fd68
b=0x61fd67
hello3你好
hello3你好
hello3你好
hello
zs
world
show2 start
sum=5
show2 end
#include "iostream"
#include <cstring>//需要包含整个头文件
using namespace std;
void test()
{
int arr[3] = {1, 2, 3};
for (int i = 0; i < 3; i++)
{
cout << arr[i] << " ";
}
cout << endl;
//清空数组
memset(arr, 0, sizeof(arr));
for (int i = 0; i < 3; i++)
{
cout << arr[i] << " ";
}
cout << endl;
//复制数组
int arr2[3] = {22, 33, 44};
int copyArr[sizeof(arr2) / sizeof(arr2[0])];
memcpy(copyArr, arr2, sizeof(arr));
for (int i = 0; i < 3; i++)
{
cout << copyArr[i] << " ";
}
cout << endl;
}
int main()
{
test();
return 0;
}
1 2 3
0 0 0
22 33 44
一维数组和指针
指针的算术
将一个整型变量加1后,其值将增加1.
但是将指针变量(地址的值)加1后,增加的量等于它指向的数据类型的字节数。
#include "iostream"
using namespace std;
void test()
{
char a;
cout << "sizeof(char)=" << sizeof(char) << endl;
short b;
cout << "sizeof(short)=" << sizeof(short) << endl;
int c;
cout << "sizeof(int)=" << sizeof(int) << endl;
double d;
cout << "sizeof(double)=" << sizeof(double) << endl;
cout << "a的地址是:" << (void *)&a << endl;
cout << "a的地址+1是:" << (void *)(&a + 1) << endl;
cout << "b的地址是:" << (void *)&b << endl;
cout << "b的地址+1是:" << (void *)(&b + 1) << endl;
cout << "c的地址是:" << (void *)&c << endl;
cout << "c的地址+1是:" << (void *)(&c + 1) << endl;
cout << "d的地址是:" << (void *)&d << endl;
cout << "d的地址+1是:" << (void *)(&d + 1) << endl;
}
int main()
{
test();
return 0;
}
sizeof(char)=1
sizeof(short)=2
sizeof(int)=4
sizeof(double)=8
a的地址是:0x61fdef
a的地址+1是:0x61fdf0
b的地址是:0x61fdec
b的地址+1是:0x61fdee
c的地址是:0x61fde8
c的地址+1是:0x61fdec
d的地址是:0x61fde0
d的地址+1是:0x61fde8
数组的地址
1 数组在内存中占用的空间是连续的
2 C++将数组名解释为数组第0个元素的地址
3 数组第0个元素的地址和数组首地址的取值是相同的
4 数组第n个元素的地址是:数组首地址+n
5 C++编译器把数组名[下标] 解释为 *(数组首地址+下标)
数组的本质:
数组是占用连续空间的一块内存,数组名被解释为数组第0个元素的地址。C++操作这块内存有两种方法:数组解释法和指针表示法,它们是等价的。
数组名不一定会被解释为地址:
在多数情况下,C++将数组名解释为数组的第0个元素的地址,有一种情况比较例外,就是sizeof运算符用于数组名时,将返回整个数组占用内存空间的字节数。
经常听到有些人说数组名就是地址,这种说法非常的不专业。
还有就是数组名时常量,不可以修改,不要说成指针,指针的值是可以修改的。