C/C++区别有哪些?很多人都不知道的比较方法
C/C++从以下几个方面的比较:
关键字的个数:
c语言:C99版本,32个关键字
C++:C98版本,63个关键字源文件:
C源文件后缀.c,C++源文件后缀.cpp,如果在创建源文件时什么都不给,则默认是.cpp变量定义或声明位置:
C语言必须在第一行定义;C++不做要求函数:
(1)返回值
C语言中,如果一个函数没有指定返回值类型,默认返回int型;
C++中,对于函数返回值的检测更加严格,如果一个函数没有返回值,则必须指定为void.
(2)参数列表
C语言中,如果函数没有指定参数列表时,默认可以接受任意多个参数;但在C++中,因为严格的参数类型检测,没有参数列表的函数,默认为void,不接受任何参数。缺省参数:
缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则,使用指定的实参。
//1.实现缺省参数void test(int a = 50){ cout a endl; } int main(){ Test(); // 输出50 Test(100); // 输出100}
(1)全缺省参数:将所有参数的缺省值全部给出//代码
// 实现全缺省参数void Test(int a = 1,int b = 2,int c = 3){ cout a "" " " b "" " " c endl; } int main(){ Test(); //1 2 3 Test(100); //100 2 3 Test(100, 200); //100 200 3 Test(100, 200, 300); //100 200 300}
(2)半缺省参数:规定,缺省值只能从右往左传//代码
// 实现半缺省参数 注:缺省值只能从右往左传void test1(int a = 1, int b = 2, int c = 3){ cout a "" " " b "" " " c endl; } void test2(int a , int b = 2, int c = 3){ cout a "" " " b "" " " c endl; } void Test3(int a , int b , int c = 3){ cout a "" " " b "" " " c endl; } void Test4(int a = 1, int b , int c = 3)//不能通过编译,因为它违背了缺省值只能从右往左依次来给这一规定{ cout a "" " " b "" " " c endl; } void Test5(int a = 1, int b = 2, int c )//不能通过编译,因为它违背了缺省值只能从右往左依次来给这一规定{ cout a "" " " b "" " " c endl; } void Test6(int a = 1, int b , int c )//不能通过编译,因为它违背了缺省值只能从右往左依次来给这一规定{ cout a "" " " b "" " " c endl; } void Test7(int a , int b = 2, int c )//不能通过编译,因为它违背了缺省值只能从右往左依次来给这一规定{ cout a "" " " b "" " " c endl; } int main(){ Test1(); //1 2 3}
注意:
a. 带缺省值的参数必须放在参数列表的最后面。b. 缺省参数不能同时在函数声明和定义中出现,只能二者则其一,最好放在函数声明中。c. 缺省值必须是常量或全局变量。
C语言不支持缺省参数
函数重载
函数重载指在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(个数、类型、类型的次序)必须不同。
//函数重载void Add(); void Add(int a); //行参个数不一样void Add(char b); //行参类型不同void Add(int a, char b); void Add(char a, int b); //行参类型的次序不同
仅仅返回值的类型不同,是不能构成函数重载的。
//仅仅返回值的类型不同,是不能构成函数重载的void Add(int a, int b){ } int Add(int a, int b){ return a + b; } int main(){ Add(1, 2); //因为这样会造成调用不明确,两函数都可以被调用 return 0; }
C++支持函数重载的原因:VS编辑器在底层将函数参数的类型编译到函数的名字中,因此原函数名就被换成了另外一个独一无二的名字。
int Add(int a, int b); // ?Add@@YAHHH@Zchar Add(int a, int b); // ?Add@@YADHH@Zchar Add(char a, char b); // ?Add@@YADDD@Z
C语言不支持函数重载的原因:所生成的新的函数名还是相同的。只是在函数名前加了_
C++中将函数按C语言风格编译,只需在函数前加 extern “c”
extern "C" int Add(char a, int b);
引用
C语言中函数有两种传参方式:传值和传址
传值:在函数调用过程中会生成一份临时变量用形参代替,最终把实参的值传递给新分配的临时变量即形参。
传值优点:函数的副作用不会影响到外部实参。
传值缺点:不能通过修改参数来改变外部实参。
传指:在函数调用过程中会生成一份临时变量用形参代替,最终把实参的地址传递给新分配的临时变量。
传指优点:节省空间,效率高,改变参数可以改变外部实参。
传指缺点:指针不安全,函数的副作用会影响外部实参。
C++中:
引用:
(1)概念:引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它的引用变量共用同一块内存空间。
(2)形式:类型&
引用变量名=引用实体
//引用int main(){ int a = 10; int& ra = a; PRintf("%p\n", a); printf("%p\n", ra); //ra和a的地址相同,说明ra和a是同一个实体,他们共用同一块内存空间 ra = 3; printf("%d\n", a); //3 return 0; }
注:
a. 引用在定义时,必须初始化。 b. 一个变量可以被多次引用。 c. 引用一旦引用了一个实体,就不能在引用其他实体。 d. 引用变量的生命周期比实体的生命周期短。
(3)常引用
常引用int main(){ const int a = 1; //int& ra = a; //编译会出错,因为实体a是常量 const int& ra = a; double b = 12.34; //int& rb = b; //编译会出错,因为类型不同 const int& rb = b; printf("rb=%d\n", rb); //rb=12 b = 5.0; printf("b=%f\n", b); //b=5.0 printf("rb=%d\n", rb); //rb=12 //b的值改变,但rb的值并没有随之改变,说明rb和b是两个不同的实体}
(4)数组引用
//数组引用int a[10]; //数组a的类型为 int[10]int(& ra)[10] = a;
(5)引用场景:
a.用引用作为函数的参数来改变实参。
void Swap(int* pLeft, int* pRight){ int temp = *pLeft; *pLeft = *pRight; *pRight = temp; } void Swap(int& left, int& right){ int temp = left; left = right; right = temp; } //如果用引用时不想改变实参的值,则给引用前加constvoid Swap(const int& left, const int& right); int main(){ int a = 10; int b = 20; Swap(& a, & b); //通过传地址来改变实参 printf(" a=%d ", a); printf(" b=%d\n", b); Swap(a, b); //通过引用来改变实参 printf(" a=%d ", a); printf(" b=%d\n", b); }
b.用引用变量作为函数的返回值 //代码
情形1:int& FunTest(){ int a = 10; return a; } int main(){ int b = FunTest(); //将函数的返回值赋给了b printf("b=%d\n", b); //b=10 printf("b=%d\n", b); //b=10 printf("b=%d\n", b); //b=10 return 0; } 情形2:int& FunTest2(){ int a = 10; return a; } int main(){ int& b=FunTest2(); //将函数的返回值作为实体, printf("b=%d\n", b); //b=10 printf("b=%d\n", b); //随机值 printf("b=%d\n", b); //随机值 return 0; } 情形3:int& FunTest3(int& a){ a = 10; return a; } int main(){ int b; int& rb = FunTest3(b); printf("b=%d\n", b); //b=10 printf("rb=%d\n", rb); //rb=10 printf("rb=%d\n", rb); //rb=10 printf("rb=%d\n", rb); //rb=10 return 0; } 注意:不能返回栈空间上的引用
传值、传指、引用 效率比较
//比较struct BigTyPE{ int array[10000]; } ; void FunTest(BigType BT)//传值或传址{ } void FunTest(BigType& bt)//引用{ } void TestFunTestRumTime(){ BigType bt; size_t Start = GetTickCount(); for (i = 0; i 1000000; i++) { FunTest(bt); //传值或传引用 FunTest(& bt); //传址 } size_t End = GetTickCount(); printf("%d\n", End - Start); } //此代码检测出传值最慢,而传址和引用速度快且用时差不多相同
引用和指针有什么区别?
相同点:
列表内容
底层的处理方式相同,都是按照指针的方式实现的。
引用变量在底层所对应指针的类型:
引用变量实体的类型* const
不同点:
引用必须要进行初始化;指针不作要求。
普通类型的指针可以在任何时候指向任何一个同类型对象;而引用一旦引用一个实体,就不能再引用其他实体。
指针++:指向下一个地址; 引用++:给数值++。
在sizeof中含义不同:引用结果为引用类型的大小;而指针始终是 地址*空间所占字节个数。
指针需要手动寻址;而引用通过编译器寻址。
引用比指针使用起来相对安全。
命名空间
在C++中,变量、函数和类都是大量存在的,这些变量、函数和类的名称将都存在于全局命名空间中,会导致很多冲突,使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染。
命名空间的定义
//命名空间namespace n1{ int a = 30; void FunTest() { printf("N1::FunTest()\n"); } } //N1的命名空间int a = 20; void FunTest(){ printf("::FunTest()\n"); } //在全局作用域中int main(){ int a = 10; printf("%d\n", a); printf("%d\n", ::a); ::FunTest(); printf("%d\n", N1::a); N1::FunTest(); return 0; } //命名空间的嵌套namespace N2{ int a = 40; void FunTest() { printf("N2::FunTest()\n"); } namespace N3 { int a = 50; void FunTest() { printf("N2::N3::FunTest()\n"); } } } int main(){ N2::FunTest(); N2::N3::FunTest(); return 0; } // 在同一个工程里允许存在多个相同名称的命名空间,编译器最后会合成到同一个命名空间中namespace N1{ int b = 70; void Test() { printf("N1::Test()\n"); } }
说明
a.一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。
b.没有名称的命名空间只能在当前文件中使用,它里面定义的变量相当于工程里面的全局变量。命名空间的使用
//命名空间的使用namespace N1{ int a = 1; int b = 2; int c = 3; /*void FunTest1() { } void FunTest2() { } */} //法二:using N1::b; //法三:using namespace N1; int main(){ int a = 4; //法一: printf("a=%d\n", N1::a); //a=1 printf("b=%d\n", b); //b=2 printf("c=%d\n", c); //c=3}
C++输入输出:
//代码
//C++输入输出#include iostream> using namespace std; //std标准命名空间int main(){ int a = 10; double b = 3.14; char c = 'c'; cout a ; cout b '\n'; cout c endl; cout a " " b " " c endl; cin > > a ; cin > > b > > c; return 0; } // cout:标准命名空间重输出流对象 输出操作符 // cin:标准命名空间重输入流对象 > > 输入操作符
相关推荐:
C# 中的 == 和 equals()有什么区别
C# 中的 == 和 equals()区别
视频:C++视频教程
以上就是C/C++区别有哪些?很多人都不知道的比较方法的详细内容,更多请关注其它相关文章!
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: C/C++区别有哪些?很多人都不知道的比较方法
本文地址: https://pptw.com/jishu/593132.html