二:
cin >>
cout <<
函数重载 overload
int func()
和int func(int a)
Extern "C" :
不按照cpp的规则编译,按照C语言的规则
Extern “C” void func (int a) {
}
或者
Extern “C” {
void func (int a) {
}
void func () {
}
}
// 会报错 因为c不支持函数重载
放在函数声明的地方 不要放在函数实现的地方:
extern "C" void func();
void func() {
cout << "func" << endl;
}
将文件整体按照c方式编译:
extern "C" {
#include "sum.h"
}
如果想让自己编写的c库,可以供c或者cpp来调用,可以在自己的c库中加入宏定义:
#ifdef __cplusplus // cpp文件第一行默认都有这个宏定义
entern "C" {
#endif
// 方法实现
#ifdef __cplusplus
}
#endif
cpp支持默认参数:
void func (int a = 10, int b = 20) {
cout << "a" << a << endl;
cout << "b" << b << endl;
}
默认参数需要从右到左逐个设置,区别于swift
如果函数声明和实现分开,默认参数必须放在函数声明的地方
三:
内联函数 inline
编译器会将内联函数调用直接展开为函数体代码,省去了开辟函数栈空间的步骤,更快更强。
注意:
1.内联函数尽量不要超过10行代码
2.内联函数只是建议编译器内联,不一定会真正成为内联函数,比如内联函数是递归函数,就会内联失败
3.调用频率高的函数可以声明为内联函数
4.函数声明和实现地方最好都加inline
关键字
5.但是如果函数有默认参数,则只能加载函数声明的地方
inline int add(int a, int b) {
return a + b;
}
区别于宏定义:
宏定义没有语法检测
引用
相当于变量的别名
实质就是指针
指针可以随时更改指向的地址,引用不可以改
不存在引用的引用、指向引用的指针
存在价值:
- 比指针更安全(指针可以被随便改)
- 函数返回值可以被赋值
// 指针操作
int a = 10;
int *p = &a;
*p = 20;
cout << a << endl;
// 引用操作
int b = 10;
int &reference = b;
reference = 30;
cout << b << endl;
const
const
修饰右边的内容
int age = 10;
// *p0是常量 p0不是常量
const int *p0 = &age;
// *p1是常量 p0不是常量 跟上面一样
int const *p1 = &age;
// p2是常量 *p2不是常量
int * const p2 = &age;
// *p3 和 p3都是常量
const int * const p3 = &age;
// *p4 和 p4都是常量 跟上面一样
int const * const p4 = &age;
拓展:常引用int const &a
等同于const int &a
、常量指针int const *p
注意:当常引用指向了不同类型的数据时,会产生 临时变量 ,即引用指向的并不是初始化时的那个变量:
int age = 10;
const long &rAge = age;
age = 20;
cout << age << endl; // 20
cout << rAge << endl; //10
四、五:
类的定义
struct
和class
定义的都是 类
// 定义一个学生类
struct Student {
int age;
void setAge(int newAge) {
age = newAge;
}
};
int main(int argc, const char * argv[]) {
Student stu;
stu.age = 10;
cout << stu.age << endl;
return 0;
}
注意:
上面代码在mian
中声明的Student
对象是存储在 栈 上,由系统自动管理内存。
struct
和class
的区别是,struct
中默认含有public
关键字,而class
默认是private
:
struct Student {
public:
...
};
对象访问属性是点语法.
指针访问属性是箭头语法->
跟数组相似,对象指针的地址,也是对象中第一个属性的地址:
struct Student {
int age;
};
int main(int argc, const char * argv[]) {
Student stu;
stu.age = 10;
cout << &stu.age << endl;
cout << &stu << endl;
// 打印结果是两个值一样
return 0;
}
对象的方法访问对象的属性,是通过调用方法时候,自动传入对象的地址(在方法中的体现是this
),然后在方法内通过地址偏移进行访问属性:
struct Student {
int age;
int name;
//
void display() {
// this就是下面mian函数中stu的地址
this->age = 20; // move [stu] 20
this->name = 30; // move [stu + 4] 20
}
};
int main(int argc, const char * argv[]) {
Student stu = Student();
// 函数放在函数代码区,编译后就确定了函数的地址了,调用的本质是直接call xxxxxxxx
stu.display(); // 调用的时候会自动传入对象stu的地址
return 0;
}
六:
栈空间:
程序运行后,内存空间分为:栈空间、堆空间、代码区和常量区
其中堆空间的使用需要我们手动申请和手动释放:
void stackFunc() {
int *p = (int *)malloc(4);
*p = 20;
free(p);
// free 和 malloc 是一一对应的关系
}
cpp中还提供了另一对关键字new
和delete
来使用堆空间:
void stackFunc() {
int *p = new int;
delete p;
}
申请数组空间的使用:
方式一:
void applyArray() {
int *p = (int *)malloc(sizeof(int) * 10);
p[0] = 1;
p[1] = 2;
free(p);
}
方式二:
void applyArray() {
int *p = (int *)new int[10];
p[0] = 1;
delete []p;
}
注意
new
一定是对应delete
,new[ ]
一定对应delete[ ]
重置内存函数memset
:
重置对象:
int *p = (int *)new int[10];
memset(p, 0, sizeof(int)); // 地址,重置内容,重置的空间大小
//从p开始的四个字节,每一个字节都放0
重置数组:
struct Student {
int age;
};
int main(int argc, const char * argv[]) {
// 初始化一个数组 保存三个Student对象
Student stus[] = {{1},{10},{3}};
// 数组名就是数组的首地址
memset(stus, 0, sizeof(Student));
return 0;
}
初始化思考:
// 没有初始化
int *p = new int;
// 初始化为0
int *p1 = new int();
// 初始化为5
int *p2 = new int(5);
// 数组没有初始化
int *p3 = new int[3];
// 数组初始化为0
int *p4 = new int[3]();
// 数组初始化为0 , 只有数组才可以用大括号
int *p5 = new int[3]{};
// 数组首元素初始化为5, 后面元素初始化为0
int *p6 = new int[3]{5};
构造函数:
类在某些情况下,默认会创建一个空参构造函数。
主动显式声明一个构造函数后,初始化的时候就必须调用声明的。
使用malloc
生成的类对象,不会调用构造函数!!!
struct Student {
int age;
// 构造函数:函数名跟类名一致,且没有返回值
Student() {
}
// 构造函数可以有多个,重载overload
Student(int age) {
this->age = age;
}
};
// 存放在全局区
Student g_st1;
Student g_st2(); //这是函数⚠️⚠️
Student g_st3(1);
int main(int argc, const char * argv[]) {
// 存放在栈区
Student st1;
Student st2(); //这是函数⚠️
Student st3(3);
// 存放在堆区
Student *p1 = new Student;
Student *p2 = new Student();
Student *p3 = new Student(4);
return 0;
}
没有显示声明构造函数的情况下,全局区的变量会自动被初始化,栈空间的不会。
声明构造函数后,只有全局区的变量才会自动初始化,栈区和堆区的都不管。
网友评论