栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++基础(二)——基本语法

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++基础(二)——基本语法

01 带形参默认值的函数

===>形参带默认值的函数

1.给默认值的时候,从

2.调用效率的问题

3.定义出可以给形参默认值,声明也可以给形参默认值

4.形参给默认值的时候,不管是定义处给,还是声明处给,形参默认值只能出现一次

#include
using namespace std;

int sum(int a, int b = 20);
//若为 int sum(int a = 10, int b) 会报错 默认从右向左给
int sum(int a = 10, int b);
int main()
{
	int a = 10;
	int b = 20;

	int ret = sum(a, b);
	
	cout << "ret:" << ret << endl;

	
	ret = sum(a);

	
	ret = sum(); // sum(20, 50);

    system("pause");
	return 0;
}

int sum(int a, int b)
{
	return a + b;
}

运行结果:

02 inline内联函数

1.inline内联函数 和 普通函数的区别???

inline内联函数:在编译过程中,就没有函数的调用开销了,在函数的调用点直接把函数的代码进行展开处理了,inline函数不再生成相应的函数符号

2.设置成内联函数准则:

短时间内多次调用且函数内部实现较为简单

3.inline只是建议编译器把这个函数处理成内联函数

但是不是所有的inline都会被编译器处理成内联函数 ——递归/函数内部代码过多

4.debug版本上,inline是不起作用的; inline只有在release版本下才能出现

inline int sum(int x, int y)  // *.o   sum_int_int  .text
{
	return x + y;
}
int main()
{
	int a = 10;
	int b = 20;

	int ret = sum(a, b); 
	// 此处有标准的函数调用过程  参数压栈,函数栈帧的开辟和回退过程
	// 有函数调用的开销   
	// x+y  mov add mov     1000000 x+y
    //例如,循环100次sum函数调用,可能函数调用时间开销大过内部指令生成的时间,则函数调用的开销过大,inline可以省去函数调用开销(参数压栈 函数栈帧的开辟和回退) 
    //相当于ret = a + b;

	return 0;
}
03 函数重载 1.定义

一组函数,其中函数名相同,参数列表的个数或者类型不同,那么这一组函数

就称作函数重载。

2.C++为什么支持函数重载,C语言不支持函数重载?

C++代码产生函数符号的时候,函数名+参数列表类型组成的!

C代码产生函数符号的时候,==函数名=来决定!

3.函数重载需要注意些什么?

1.一组函数要称得上重载,一定先是处在同一个作用域当中的。

在局部进行函数声明,会在局部作用域选择声明的函数

bool compare(int a, int b) // compare_int_int
{
	cout << "compare_int_int" << endl;
	return a > b;
}
bool compare(double a, double b) // compare_double_double
{
	cout << "compare_double_double" << endl;
	return a > b;
}
bool compare(const char *a, const char *b) // compare_const char*_const char*
{
	cout << "compare_char*_char*" << endl;
	return strcmp(a, b) > 0;
}
int main()
{
	bool compare(int a, int b); // 函数的声明  优先调用

	compare(10, 20); // call compare_int_int
	compare(10.0, 20.0); // double -> int 造成错误
	compare("aaa", "bbb"); // const char* => int

	return 0;
}

//输出结果会优先调用compare_int_int,造成错误

2.const或者volatile的时候,是怎么影响形参类型的。

void func(int *a) {}  // int
void func(int *const a) {}  
int main()
{
	int a = 10;
	const int b = 10;

	cout << typeid(a).name() << endl;
	cout << typeid(b).name() << endl;

	return 0;
}
//const不会改变类型还是int 造成函数重定义
//加入指针后 则可以被重载 不加指针 相当于函数重定义

3.一组函数,函数名相同,参数列表也相同,仅仅是返回值不同?

不叫重载(重载和返回值无关

4.C++和C语言代码之间如何互相调用

C 调用 C++:无法直接调用,怎么办?

把C++源码扩在extern “C”

//c++文件中写入
extern "C"{
	int sum(int a, int b) // sum_int_int  .text
	{
		return a + b;
	}
}

C++ 调用 C代码:无法直接调用,怎么办?

把C函数的声明扩在extern "C"里面

//c++文件中写入
extern "C" // 按C的规则生成符号
{
	int sum(int a, int b);  // sum  "UND"
}

int main()
{
	int ret = sum(10, 20);  
	cout << "ret:" << ret << endl;
	return 0;
}
5.多态

静态(编译时期)的多态:函数重载

动态(运行时期)的多态:虚函数

04 const用法

1.c++的const

必须初始化的,叫常量

叫常变量 因为初始值不是立即数,是一个变量

2.C和C++中const的区别是什么?

const的编译方式不同,C中,const就是当作一个变量来编译生成指令的。

C++中,所有出现const常量名字的地方,都被常量的初始化替换了!!!

3.const怎么理解?

const修饰的变量不能够再作为左值!!!初始化完成后,值不能被修改!!!

int main()
{
	int b = 20;
	const int a = b;  // 已经改了!!!
	//int array[a] = {};

	int *p = (int*)&a;
	*p = 30;

	// 20 30 20
	printf("%d %d %d n", a, *p, *(&a));

	return 0;
}

05 const与一二级指针结合应用 1.const+一级指针

const和一级指针的结合

const修饰的量 叫常量

普通变量的区别是什么?

C++有两点区别:

1.编译方式不同 2.不能作为左值了

const修饰的量常出现的错误是:

1.常量不能再作为左值 《= 直接修改常量的值

int main() {
    const int a = 10;
    a = 20;//直接修改常量的值
    return 0;
}

2.不能把常量的地址泄露给一个普通的指针或者普通的引用变量 《= 可以间接修改常量的值

int main() {
    const int a = 10;
    int *p = &a;//常量的地址泄露给一个普通的指针或者普通的引用变量==
    //应改为 const int *p = &a;
    return 0;
}

const和一级指针的结合:有两种情况

C++的语言规范:const修饰的是离它最近类型

情况1:

const int *p = &a;  
*p = 20;//不能赋值 
p = &b;//可以指向不同类型的内存
//可以任意指向不同的int类型的内存,但是不能通过指针间接修改指向的内存的值

情况2:

int const* p;//等同于 const int* p


int *const p = &a; 
p = &b;//地址不能被修改 
*p = 20;//值可以被修改
//这个指针p现在是常量,不能再指向其它内存,但是可以通过指针解引用修改指向的内存的值

情况3:

const int *const p = &a; 
/
	return 0;
}
06 左值引用与右值引用 1.引用和指针的区别?

引用是一种更安全的指针。

1.引用是必须初始化的,指针可以不初始化

2.引用只有一级引用,没有多级引用;指针可以有一级指针,也可以有多级指针

3.定义一个引用变量,和定义一个指针变量,其汇编指令是一模一样的;通过引用

变量修改所引用内存的值,和通过指针解引用修改指针指向的内存的值,其底层

指令也是一模一样的

void swap(int *x, int *y)
{
	int temp = *x;
	*x = *y;
	*y = temp;
}
void swap(int &x, int &y)
{
	int temp = x;
	x = y;
	y = temp;
}
int main()
{
	int a = 10;
	int b = 20;
	//swap(&a, &b);
	swap(a, b);
	cout << "a:" << a << " b:" << b << endl;

	//int a = 10;
	//int *p = &a;
	//int &b = a;
	//int &c = 20;
	/
	const int &d = 20;
	return 0;
}
07 const、指针、引用结合
int main()
{
	//int a = 10;
	//int *p = &a;
	//const int *&q = p;
	//const int **q = &p; //const int** <= int**

	//int a = 10;
	//const int *p = &a;
	//int *&q = p;
	//int **q = &p;
	//int** <= const int**

	//int a = 10;
	//int *const p = &a;
	//int *&q = p; 
	//int **q = &p; // *q = 

	// 写一句代码,在内存的0x0018ff44处写一个4字节的10
	//int *const &p = (int*)0x0018ff44;

	//int a = 10;
	//int *p = &a;
	//const int *&q = p; // typeid(q).name()
	// const int*   int* 

	return 0;
}
08 new和delete语法

new和delete

new和malloc的区别是什么?

delete和free的区别是什么?

malloc和free,称作C的库函数

new和delete,称作运算符

new不仅可以做内存开辟,还可以做内存初始化操作

malloc开辟内存失败,是通过返回值和nullptr做比较;

而new开辟内存失败,是通过抛出bad_alloc类型的异常来判断的。

1.new的种类
// new有多少种?
int *p1 = new int(20);

int *p2 = new (nothrow) int;

const int *p3 = new const int(40);

// 定位new  
int data = 0;
int *p4 = new (&data) int(50);
cout << "data:" << data << endl;
2.new、delete例子
int main()
{
	int *p = (int*)malloc(sizeof(int));
	if (p == nullptr)
	{
		return -1;
	}
	*p = 20;
	free(p);

	int *p1 = new int(20);
	delete p1;

	int *q = (int*)malloc(sizeof(int) * 20);
	if (q == nullptr)
	{
		return -1;
	}
	free(q);

	//int *q1 = new int[20];
	int *q1 = new int[20](); // 20个int sizeof(int) * 20
	delete[]q1;

	return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/850036.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号