1.类 class
#include <iostream>
using namespace std;
struct Student{
int sid;
int score;
//C++ 可以在结构体中定义函数
void hehe(){
cout << "Hehe..." << endl;
}
};
/*
之所以结构体中可以定义函数,是因为C++并没有区别对待结构体与类
*/
class Student{
public: //如果不加说明,默认是不公开的
int sid;
int score;
void hehe(){
cout << "Hehe..." << endl;
}
}
int main(){
Student zs;
//C: struct Student zs;
zs.sid = 100;
zs.hehe(); //变量调用
/*
Student *pz;
pz = &zs;
pz->hehe();
指针调用
*/
cout << "Hello zs!" << endl;
return 0;
}
2.bool
C语言
int flag = 5 > 3;
true 1
false 0
C语言真假和整型是可以做转换的
!0 ---> true
0 ---> false
C++
同样整型可以与真假相联系
bool值取true or false
bool flag;
flag = 123;
cout << flag << endl;
output: 1
说明C++还是对整形和布尔型进行了一个转换的
但如果在C语言中将flag定义为int,其输出仍为123
3.auto
令编译器推断变量的类型,但是在定义变量的时候应该让编译器能够判断变量的类型
下面是错误示范:
auto a;
a = 2;
C语言是一种强类型的语言,即每一个变量应该有明确的类型
所以一般不推荐在定义变量的时候使用auto
4.引用 reference
首先看这样一个例子:
int a = 3;
//定义a这个变量,并且拿3给a做初始化
//此处'='是初始化,不是运算符
int a;
a = 3;
//定义a这个变量但是没有初始化,把3赋值给a
//此处'='为赋值,是运算符
再来回忆一下指针:
int *p;
//要看定义了什么,先看中心点,中心点永远是名字,所以为p
//抓住了中心点以后再向两边看谁靠的近,*靠的更近,所以p是一个指针
//再往远看是int,所以指针是指向int的。则p是指向int的指针
//*不是运算符,仅表示一个类型
int a = 3;
p = &a;
*p = 6;
//此处的*为运算符,与上面的*是不一样的
//意义为根据后面指针p的值去找到p所指向的a
接下来看引用:
int b = 6;
int &r = b;
r = 123;
cout << b << endl;
output: 123
//看r的定义:中心点是r,右边是初始化内容,不看;左边&靠得最近
//此处&并不是取地址,而同样是一个类型,表示引用型。再往左边看是int
//所以r是一个int的引用。这个引用是拿b来初始化的,但并不是把b的值赋给r
//是拿b过来初始化,让r变成b的引用,即取一个“外号”,此时r与b等价
引用同指针一样,一般应用在函数中
void fun(int *p){
*p = 666;
}
int a = 3;
fun(&a);
/*
C语言中分为值传递与地址传递
在一个普通函数中如果采用值传递
比如func(c)
可能会发生很大的空间的复制,比较低效
*/
void fun(int &k){
k = 2233;
}
int b = 6;
fun(b);
/*
C++用值传递与引用传递
此处fun(b)传引用
如何区分一个函数是传值还是传引用呢?
看函数的参量列表中的参量是否为引用型
C++规定:引用必须在创建时指明它所引的对象
一旦绑定不可再更改
*/
int &r = 123; //error
const int &r = 123;
int &&r = 123; //右值引用,暂不深入
5.赋值
int a, b, c;
a = b = c = 3;
//C++和C语言都可通过
(a = b = c = 3) = 666;
cout << a << " " << b << " " << c << endl;
//C++可通过,但是C语言会报错
C++ output: 666 3 3
/*
C++跟C语言赋值有一点不一样
C语言:a = 3,是把3赋值给a,然后整个赋值语句的值为3
C++: a = 3,把3赋值给a,然后整个赋值语句变成左边a的引用
(a = 3) = 666;
在C语言中即为(3) = 666;
C++: (a) = 666;
a = b = c = 3;
C++中逐步赋值为:
a = b = c;
a = b;
a;
*/
int a = 3;
C++给出了一种不用等号初始化的方法:
int a {3};
int array[5] {1, 2, 3, 4, 5};
同样可以用来初始化结构体变量,类的对象
6.动态内存分配
C:
int *p;
p = (int*)malloc(sizeof(int)*10);
/*
malloc()返回值为void*,被强制转换为(int*)
malloc()不关心开辟的内存空间是用来放什么的
*/
C++:
int *p;
p = new int;
/*
new关键字:使C++申请一个空间用来放int,并且把
用于存放int的空间的地址返回给p
new后面跟的不像malloc()一样是空间的大小,而是
一个类型
p = new int[10];
int[10]是一个类型,是由10个int组成的数组的类型
*/
空间申请好之后,需要记得释放空间
C:
free(p);
C++:
delete p;
/*
简单类型的数组可以直接用delete p,但如果是自己定义的结构体/类
的数组,比如p = new Student[10],应为delete [] p,如果写为delete p
这些元素的析构会出问题
所以建议在释放数组的时候,一律使用delete []
*/
7.新的for语句(C++11之后)
for(int x : array)
cout << x << ' ';
//冒号右边是容器,可以是数组,也可以是vector等各种容器
int array[5] = {1, 2, 3, 4, 5};
for(int x : array){
x += 100;
cout << x << ' ';
}
cout << endl;
for(int i = 0; i < 5; i++)
cout << array[i] << ' ';
cout << endl;
output:
101 102 103 104 105
1 2 3 4 5
/*
int x : array只是把array中元素的值给了x,而本身数组中的
1, 2, 3, 4, 5是没有改变的
如果想要改变array数组中元素的值,可以写为int &x : array
此时x是数组中元素的引用(不是元素值的引用)
如果容器中元素的类型比较复杂,可以写为auto x : array
*/
8.重载 overload
int add(int x, int y){
return x + y;
}
int add(int x, int y, int z){
return x + y + z;
}
重载:函数名一样,但调用时参量不同
因为参量不同,所以是不同的函数
而参量是否相同,是看函数原型是否相同
int add(int x, int y){
return x + y;
}
int add(int y, int x){
return x + y;
}
两个函数的函数原型都是:
int add(int, int);
所以第二个函数不是合法的重载,会被认为是函数的重定义
只有返回类型不一样,也是不能作为重载的,因为编译器
不好判断调用哪个函数
int add(int x, int y){
return x + y;
}
double add(double x, double y){
return x + y;
}
int main(){
cout << add(3, 5.5) << endl;
cout << add(3.5, 1) << endl;
return 0;
}
提示:Call to 'add' is ambiguous
当向两个函数都可以进行转化的时候
会提示函数具有二义性
struct Vector{
int x;
int y;
};
Vector operator + (const Vector &a, const Vector &b){
Vector temp;
temp.x = a.x + b.x;
temp.y = a.y + b.y;
return temp;
}
/*
为了尽量避免传结构体,所以用到了引用
const是为了避免a和b的改动
*/
int main(){
Vector a, b;
a.x = 3;
a.y = 4;
b.x = 1;
b.y = 2;
/*
C:
a.x + b.x;
a.y + b.y;
C++:
a + b; // +(Vector, Vector);
+:双目运算符,可以把'+'看作一种操作
而a, b看作是操作所需要的参数
*/
Vector sum;
sum = a + b;
cout << sum.x << ' ' << sum.y << endl;
return 0;
}
9.lambda表达式
auto f = [](int a, int b) -> int{return a + b;};
cout << f(3, 5) << endl;
output: 8
f是指向函数的一个指针,[]中写要捕获的东西,()写函数的参数
参量的类型可以写成auto,->后面{}前面写函数返回的类型
可以写成auto,{}里面写函数
当我们想用一个函数,但是又不想去写定义的时候,可以用lambda表达式