与C语言完全相同的就没必要记录了
sizeof
sizeof不是函数,是个操作
short num = 10;
cout<<"short占用内存空间为:"<<sizeof(num)<<endl;
// 2 因为short占2个字节,int 4个字节,long 4个字节,long long 8个字节
float 类型
因为编译器默认会将小数认为是double型
所以,可以在数字后面加上“f”标记这个数值是float类型。
默认情况,打印6位有效数字,“3.14” 是3位有效数字
字符串
与C语言有一点差异,两者都可以
//C语言风格
char str1[] = "hello world"; //别忘了中括号
cout << str1 << endl;
//C++风格
string str2 = "hello siri"; //记得包含头文件string.h
cout << str2 << endl;
数据输入
cin>>
输入字符串遇到空格就结束- bool型输入“true” 返回 0,输入100 返回 1
cin >> inputint;
cin >> inputchar;
cin >> inputstring; //hello siri
cin >> inputbool; //100
cout << inputint << endl;
cout << inputchar << endl;
cout << inputstring << endl; //hello 输入遇到空格结束
cout << inputbool << endl; //1 输入非0值 返回都是真
取模运算
- 两数相除,分母不能取0
- 两个小数不能进行取模运算
随机数种子
srand((unsigned int)time(NULL))
,记得添加头文件 <ctime>
程序内存模型
代码区
存放所有代码和注释,操作系统管理
全局区
全局变量(不在任何函数中,包括main函数以外)和静态变量(static)及常量(string字符串常量 和 const变量),操作系统管理
栈区
编译器分配,管理生成和消亡,存放参数值和局部变量
堆区
程序员分配,管理生成和消亡,若程序员不释放,程序结束后由操作系统释放
程序运行前
编译后,生成exe文件,未执行前:
代码区
- 存放CPU执行的机器指令
- 代码区是共享的,只存一份代码
- 代码区是只读的,防止意外修改
全局区
- 存放全局变量和静态变量
- 全局区包含常量区,字符串常量和其他常量(const)都存放在常量区
程序运行后
栈区
- 由编译器自动分配,存放函数的参数和局部变量等
- 不要在函数内return 局部变量的地址,因为局部变量存放在栈,但是函数执行完会释放栈区,所以即使*p所指的地址没变,里面的值已经被释放了
int * func()
{
int a = 10;
return &a; //返回这个局部变量的地址
}
int main()
{
int *p = func();
cout<<*p<<endl; //10 是编译器的保留
cout<<*p<<endl; //乱码 第二次编译器不再保留
}
堆区
- 在C++中使用 new关键字 在堆区开辟内存
int * func()
{
int *p = new int (10);
return p; //返回这个局部变量的地址
}
int main()
{
int *q = func();
cout<<*q<<endl; //10 是编译器的保留
cout<<*q<<endl; //10 指向p的栈已经在func结束删除了,但是这里q接下了位置,并且所指位置的值没有释放
}
这里是用栈中的指针保存了堆区的地址编号,和上面一样,p指向的地址没有变,但是堆没有释放,所以里面的的值一直都在。
new关键字
可以在堆区中开辟内存,完全结束前,不会被自动删除,可以用delete手动删除。
new 返回数据类型的指针
string *func_new()
{
string *p = new string("这里测试new符号");
return p;
}
void test_new()
{
string *q = func_new();
cout << *q << endl;
}
int main() {
test_new();
system("pause");
/*
这里测试new符号
*/
释放new出来的数组空间,需要用
delete [] arr
int* func_new_array()
{
int* arr = new int[10];
for (int i = 0; i < 5; i++)
{
arr[i] = 10 - i;
}
return arr;
}
void test_new_array()
{
int* q = func_new_array();
for (int i = 0; i < 5; i++)
{
cout << q[i]<<endl;
}
//对数组释放
delete[] q;
}
int main() {
test_new_array();
system("pause");
/*
10
9
8
7
6
*/
引用
基本语法
作用:给变量起别名(也指向原名的地址,共享地址)
语法:数据类型 &别名 = 原名
引用的本质还是指针,不过,是不变的指针常量
注意点
-
引用必须初始化
不能int &b;
,必须int &b = a;
,像这样声明 b 的时候就确定地址 -
初始化后,就不可以改变。
int main() {
//引用
int a = 10;
int& b = a;
cout << "a = " << a << endl; //a = 10
cout << "b = " << b << endl; //b = 10
//新变量c存储20
int c = 20;
//更改引用,会出问题
b = c;
cout << "a = " << a << endl; // a = 20 会连着a的值一起修改,这有问题
cout <<" b = " << b << endl; // b = 20
system("pause");
这样操作引用的结果就是,本意不想改变a的值,实际上在更改引用的时候,连着改变了a
做函数参数
函数操作会影响输入参数的实际值,而不是浅拷贝那样使用参数作为输入。
//传递地址 交换值
void swap_by_address(int *a,int *b)
{
int temp; //int变量
temp = *a; //temp得到a地址的值
*a = *b; //交换a地址的值 和 b地址的值
*b = temp;
}
//传递引用 交换值
void swap_by_ref(int &a, int &b)
{
int temp; //传入引用(别名)
temp = a; //temp等于真实的a
a = b; 交换真实的a和b
b = temp;
}
int main() {
int swap1 = 11;
int swap2 = 22;
cout << swap1 << endl; //11
cout << swap2 << endl; //22
//swap_by_address(&swap1,&swap2); //地址传递
swap_by_ref(swap1, swap2); //引用传递
cout << swap1 << endl; //22
cout << swap2 << endl; //11
system("pause");
}
通过引用参数产生的效果和按地址传递一样,引用更明确一点。
做函数的返回值
- 不要返回局部变量的引用
引用的本质其实也就是指针(常量),back其实指的是a的位置,但是局部变量a在函数结束后就销毁了,因此别名back也不能正常使用。
int& reback()
{
int a = 10;
return a;
}
void main()
{
int &back = reback();
cout << back << endl;
cout << back << endl; //可能会乱码,和之前一样,局部变量存在栈区,函数结束就删除
system("pause");
}
- 函数调用可以作为左值
函数的返回值是引用的话,这个函数可以作左值。
int& reback()
{
static int a = 10; //记得这里用static防止被清除
return a;
}
void main()
{
int &back = reback(); //back作为reback返回值a的别名
cout << back << endl;
cout << back << endl;
reback() = 1000; //reback()=1000,等价于back=1000
cout << back << endl;
cout << back << endl;
system("pause");
}
引用的本质
引用的本质在C++内部是一个指针常量,指针指向不可变化。
void main()
{
int ref_val = 10;
int& ref = ref_val; //内部进行 int *const ref = ref_val ,也就是声明一个指针常量ref
ref = 20; //内部进行 *ref = 20 ,将指针ref的值赋值为20
cout <<"ref_val = " << ref_val << endl;
cout <<"ref = " << ref << endl;
system("pause");
}
常量引用
- 用const可以直接对引用值赋值
int main()
{
int const_ref_val = 111;
// int& const_ref = 100; //引用必须引一块合法的内存空间
const int& const_ref = 100; //编译器自动完成: int temp = 100; const int &const_ref = temp;
}
- 常用来修饰形参,防止误操作:形参误改实参
void showValue(int& val) //形参应该改为const int &val 就可以用const修饰形参,防止误更改val引用的值
{
val = 1000;
cout << "val = " << val << endl;
}
int main()
{
int show_ref_val = 10;
showValue(show_ref_val);
//这里的show_ref_val本来只是想输出,不小心在函数showValue中被修改了值,导致show_ref_val也被改为1000,这是有问题的
cout << "show_ref_val = " << show_ref_val << endl; //show_ref_val = 1000
}