C/C++区别

C/C++的区别

1,函数值的默认值
2,函数重载
3,inline函数
4,C和C++的相互调用
5,引用
6,const
7,new/delete
8,namespace

一,函数值的默认值

int Sum(int a,int b,int c)
{
   return a+b+c;
}

int Sum(int a,int b)
{
   return a+b+10;
}

1,C的函数符号生成规则——函数名(重复)

#include<iostream>
int Sum(int a,int b,int c=10)
{
    cout << “c:" << c<<endl;
     return a+b+c;
}
int main()
{
   Sum(10,20);//没有实参,形参有默认值
   Sum(102030);//有实参,也有默认值
   return 0;
}

函数默认值(形参有默认值无实参——>默认值)

没有实参,形参有默认值
有实参,形参也有默认值
(实参和形参匹配顺序自左向右)

默认值赋予规则:
1,函数的默认值赋予必须自右向左赋予(最右边的形参没有默认值时,前面不能有默认值)
2,默认值不能重复赋予
3,一般默认值加在声明上

二,函数重载

1,两个数求和(和类型无关)
a,C语言泛型,void*(不安全)
b,预定义函数(不安全)

bool Sum(int a,int b)
bool Sum(double a,double b)
bool Sum(char* a,char* b)

C++支持函数重载,C语言不支持函数重载
函数重载
1,是一种同名函数的关系
2,函数返回值不能为函数重载提供支持
函数的重载是根据函数的参数不同(只和参数有关)

1,函数符号生成规则与函数重载有关
C:
函数名相关
C++
函数原型

函数原型
函数值的返回值 函数名 (函数的形式参数数列表)
{
}

2,C++的函数符号规则

在这里插入图片描述
3,函数的参数列表不同
1,参数顺序不同
2,参数个数不同
3,参数不同

bool Compare(int,double );
bool Compare(double,int )
int main()
{
     Compare(10,20.1);
     Compare(20.1,32);
     return 0;
}

函数重载的三要素:
1,同名
2,不同参
3,同作用域(例:main函数里面和全局作用域不同)

三, inline函数 内联函数

作用:函数调用点直接代码展开

①,inline函数和宏的区别?
----->inline函数在编译阶段,类型检查和安全检查
宏在预编译阶段,是文本替换,没有检查,所以inline更安全
②,inline函数和普通函数的区别
------>inline没有开栈和清栈的开销
普通函数有开栈和清栈的开销
③inline函数和static修饰的函数的区别
------->inline将函数体放在符号表中,不生成函数符号
static 开栈清栈的开销 将g换成l,只有局部可见
④为什么不把所有函数都设置为内联函数?
缺陷:代码膨胀为代价,目标代码的指令冗杂,重复,

总结
1,堆栈的开销 >函数执行的开销 ----函数体小-----建议设为内联
2,堆栈的开销<函数执行的开销-----函数体较大------不建议设为内联

inline函数的注意事项
普通函数:
-------函数声明 .h
-------函数定义 ,c/.cpp
-------函数调用 .c/.cpp
1,定义 .h文件
2,只在release版本生效
3,给编译器的一个建议 ( 循环 ,递归不处理成内联)
4,内联是基于实现的,不是基于声明的(内联要加载到定义点)

四, C和C++相互调用

项目------>c/.cpp
1,C的代码以C++规则处理
2,C++的代码以C规则处理
应该选第二种(扩好扩,不好缩)

方法一:extern “C”(允许修改代码时)
方法二:加一个中间层(不允许修改代码)
(计算机任何问题都可以用加一个中间层来解决-----程序员的自我修养)

文本文件:
1,C编译器编译 C规则
2,C++编译器编译 C++规则

1,文件 .c
无extern“C”(不应该出现extern)
C编译器中没有_cplusplus这个宏
2,文件 .cpp
有extern“C”
C++编译器一定有_cplusplus这个宏

判断是否有_cplusplus

#ifdef __cplusplus
extern "C"
{
#endif
     int Sum(int a,int b)
     {
     return 0;
     )
#ifdef __cplusplus
}
#endif

在这里插入图片描述

总结;
1,C++调用C语言:将extern “C”
2,C调用C++语言:
①extern “C”(允许修改)
②加中间层(不允许修改)
③文本编译 ------C调用C++ ----- 用_cplusplus宏解决

五,引用

void Swap(int *a,int *b)
{
   int tmp=*a;
   *a=*b;
   *b=tmp;
}
int main()
{
    int a=10;
    int b=20;
    Swap(&a,&b);//实参传递(有歧义)
    cout << "a:" << a <<endl;
    cout << "b:" << b <<endl;
    return 0;
}
   
void Swap(int& a,int& b)
{
   int tmp=*a;
   *a=*b;
   *b=tmp;
}
int main()
{
    int a=10;
    int b=20;
    Swap(&a,&b);//实参传递(有歧义)
    cout << "a:" << a <<endl;
    cout << "b:" << b <<endl;
    return 0;
}
   

引用符:&
引用-------别名
底层是指针处理,是对引用做处理支撑
形参和实参指向同一个内存单元,因此可以修改实参的值
底层:
b有自己的内存单元,是以指针方式来处理
使用引用变量,系统自带解引用的过程
特点:
1,一定要初始化
2,不能引用不能取地址的数据
3,别名被用,不能改变
4,引用变量,只能访问其引用的变量,不能访问它本身的

   int main()
   {
   int a;
   int &b=a;
   b=10;
   return 0;
   }

六,const(C++的语法)

C
const修饰的量为常变量

常变量----编译阶段------查看常变量是否做左值
是------error
否——其他处理和变量相同

C++
const修饰的量为常量

常量-----编译阶段-------(用常量的地方替换成常量初始值的值)
常量特点:
①一定要初始化
②不允许修改
a,直接访问(a=20)
b,不允许间接访问(不允许指针指向)—杜绝间接修改常量的风险

         const int a;
         int*p=&a;//const int*p=&a;
         int*q=p;//const int*q=p;
         /*
         直接访问:a
         间接访问:*p    *q
          */ 
         int a=10;
         const int* p=&a;
         int*q =p;//const int*q=p;
         /*
         直接访问:*p a
         间接访问:*p  *q
         */ 
         int a=10;
         int *p=&a;
         const int*q=p;//出现const,从这个点看
         /*
         const *q  a
         直接访问:*q  a
         间接访问:*q*
         */
         
         
          

const和引用的结合
&不参与类型
指针转引用:( int& b=a;-------->int* b= &a;)

     const int a=10;
     int& b=a;//const int& b=a;

常引用的优化策略:
常引用能引用不能取地址的数据
不能取地址的数据放在临时量
常引用引用该临时量

const int& c=10;//正确
const int* c=&10//错误

七,new/delete(malloc/free)

malloc
void* malloc(size_t size);//viod*
void*[)
1,返回值类型不安全

int main()
{
	int* p = (int*)malloc(sizeof(int));
	*p = 20;
	free(p);
	return 0;
}
	

C++(new/delete)

int main()
{
	int* p=new int;
	*p =20;
	delete p;
	return 0;
}

1,new动态开辟
----------不仅可以开辟内存,还能初始化
2,new动态开辟数组
---------new[]----->可以零初始化
3,new内存开辟失败
--------抛出异常,异常处理机制
4,new开辟常量内存块
5,new开辟的内存位置
-------自由存储区

int main()
{
//动态开辟内存
	int *p = new int(10);//赋值并初始化
	cout << *p << endl;
//动态开辟数组
	//一维数组
	int*p = (int*)malloc(sizeof(int)*20);//数组
	free(p);
	int *q =new int [20]();//数组,零初始化
	delete[] q;
	//二维数组
	int**p =(int**)malloc(sizeof(int*)*10);
	for(int i =0;i<10;i++)
	{
		p[I] =(int*)malloc(sizeof(int)*10);
	}
	int** q =new int*[10]();
		for(int i =0;i<10;i++)
	{
		p[I] =(int*)malloc(sizeof(int)*10);
	}
//开辟常量内存
	const int* p = new const int(10);
	delete p;
//重定位new
	int a;
	char* pb =new (&a) char('a');//大的内存中获取内存单元供其他变量使用
	return 0;
}

new和malloc的区别
1,new是关键字,malloc是函数
2,new 返回值类型安全,malloc返回值类型不安全
3.new系统计算机开辟的大小,malloc程序人员计算
4,new能做初始化,malloc只能开辟内存
5,new[]开辟数组
6,内存开辟失败
new抛出异常,malloc 返回值NULL
7,new开辟常量内存
8,存储位置
new自由存储区,malloc在堆

namespace

C
全局作用域,局部作用域
C++
namespace 名字空间作用域(解决C语言命名冲突问题)
class

namespace Sa
	int Sum(int a,int b)
	{
		return a+b;
	}
	int a+b;
}
int main()
{
	Sa::a;
	Sa::Sum(10,20);

	using Sa::a;//using声明(将a暴露在using声明当前所在的作用域)
//名字作用域中所用成员都暴漏在当前using指示符所在的作用域
	using namespace Sa;
	int b=a;
	Sum(10,20);

    using namespace std;//std,C++的标准名字作用域
    std::cout << "hello world!" << std :: endl;
	return 0;
}

同名名字作用域--------合并

总结

1,函数的默认值
2,函数重载(重点)
3,inline(中等)
4,C和C++的调用
5,引用(重重点)
6,const(重点)
7,new/delete
主要是new/malloc(重点)
8,namespace

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值