C/C++基础
一、C++基础
1.C++命名空间:
为了解决合作开发时的命名冲突,C++引入了命名空间的概念。
namespace Li{ FILE fp = NULL; } namespace Han{ FILE fp = NULL; }// 两个人各自定义了以自己姓氏命名的命名空间
name是命名空间的名字,它里面可以包含变量、函数、类、typedef、#define等,最后由{}包围
使用变量、函数时要指明他们所在的命名空间,以上面的fp变量为例,可以:
Li :: fp = fopen("one.txt","r"); Han :: fp = fopen("two.txt","rb+");
::是域解析操作符 ,指明要使用的命名空间。除了直接使用域解析操作符,还可以采用using声明,例如:
1 using Li :: fp; 2 fp = fopen("one.txt","r"); 3 Han :: fp = fopen("two.txt","rb+");//打开一个文本,文件必须存在,允许读写
using声明不仅可以针对命名空间中的变量,也可以用于声明整个命名空间。
#include<stdio.h> //将类定义在命名空间中 namespace Diy{ class Student{ public: char *name; int age; float score; public: void say(){ printf("%s的年龄是%d,成绩是%f\n",name,age,score); } } } int main(){ Diy ::Student stu1; stu1.name = "小米"; stu1.age = 15; stu1.score = 92.5f; stu1.say(); return 0; }
2.C++标准库和std命名空间
C++增加了自己的头文件,例如:iostream.h用于控制台输入输出头文件 fstream.h用于文件操作的头文件 complex.h用于复数计算的头文件
C++引入命名空间的概念,将类、函数、宏统一纳入一个命名空间,这个命名空间的名字是std。对于不带.h的头文件,所有的符号都位于命名空间std中,使用时需要声明命名空间std;对于带.h的头文件,没有
使用任何命名空间,所有符号都位于全局作用域。对于原来的C语言的头文件,即使按照C++的方式来使用,即#includ<cstdio>这种形式,那么符号可以位于命名空间std中,也可以位于全局范围中。
使用C++库进行输入输出:
1 #include <iostream> 2 #include <string> 3 4 int main(){ 5 //声明命名空间std 6 using namespace std; 7 8 //定义字符串变量 9 string str; 10 //定义int变量 11 int age; 12 //从控制台获取用户输入 13 cin>>str>>age; 14 //将数据输出到控制台 15 cout<<str<<"已经成立"<<age<<"年了!"<<endl; 16 17 return 0; 18 }
string是C++中的字符串类,定义变量。在main()函数中声明命名空间std,作用范围位于main()函数内部,如果在其他函数中用到了std,需要重新声明。
1 #include<iostream> 2 3 void func(){ 4 //必须重新声明 5 using namespace std; 6 cout<<"http://yinlei.space"<<endl; 7 } 8 9 int main(){ 10 //声明命名空间std 11 using namespace std; 12 13 cout<<"yinlei"<<endl; 14 func(); 15 return 0; 16 }
若在所有的函数中都使用命名空间std,可以将它声明在全局范围中,最好是在函数内部声明命名空间std.
随用随定义。
3.C++输入输出
需要输入输出的时候,需要包含头文件iostream。
所有的局部变量都必须定义在函数开头,在定义好变量之前不能有其他的执行语句,但是C99取消了这条限制,可以在for循环的控制语句中定义变量
1 #include <iostream> 2 using namespace std; 3 4 int sum(int n){ 5 int total = 0; 6 //在for循环的条件语句内部定义变量 7 for(int i=1;i<n=;i++){ 8 total += i; 9 } 10 return total; 11 } 12 13 int main(){ 14 cout<<"Input a interge:"; 15 int n; 16 cin>>n; 17 cout<<"Total:"<<sum(n)<<endl; 18 return 0; 19 }
布尔类型(bool),C语言没有彻底从语法上支持“真”“假”,只是拿1和0代表,C++新增bool类型,占用1个字节长度,bool类型只有两个取值,true和false,但是输出bool类型的时候还是用1和0表示。
例子:提示用户输入一个整数,将该整数分别以8进制,10进制,16进制打印在屏幕上,和输入一个布尔值(0或1),以布尔方式将值打印在屏幕上
#include <iostream>
#include <stdlib.h>
using namespace std;
int main(void)
{
cout<<"请输入一个整数:"<<endl;
int x=0;
cin>>x;
cout<<oct<<x<<endl; //oct,dec,hex分别是8进制、10进制、16进制的英文缩写
cout<<dec<<x<<endl;
cout<<hex<<x<<endl;
cout<<"请输入一个布尔值(0,1):"<<endl;
bool y=false;
cin>>y;
cout<<boolalpha<<y<<endl;
system("pause");
return 0;
}
4.const变量
const用来限制一个变量,表示这个变量为常量,不能被修改,在C++中
const int m=10; int n = m;
这在C语言中,编译器会先到m所在的内存取出一份数据,再将这份数据赋给n;,而C++中,编译器会直接将10赋给m,没有读取内存的过程,和int n =10的效果是一样的,C++中的常量更类似于#define命令,C++对const的处理少了读取内存的过程
虽然const变量禁止被修改,但是可以通过指针可以修改:
1 #include<stdio.h> 2 3 int main(){ 4 const int n = 10; 5 int *p = (int*)&n;//必须强制类型转换 6 *p = 99;//修改const变量的值 7 printf("%d\n",n); 8 return 0; 9 }
&n得到的指针的类型是const int *,必须强制转换为int *后才能赋给p,否则类型是不兼容的。在C语言中,使用printf输出n的时候会到内存中获取n的值,这个时候n所在内存中的数据已经被修改成了99,所以输出结果也是99,而在c++中,printf("%d\n",10);一样,不管n所在的内存如何变化,都不会影响输出结果。C语言对 const 的处理和普通变量一样,会到内存中读取数据;C++ 对 const 的处理更像是编译时期的#define,是一个值替换的过程。
且c++中全局const变量的可见范围是当前文件,普通全局变量的作用域是当前文件,但是在其他文件中也是可见的,使用extern声明后就可以使用,比如
1 #include <stdio.h> 2 3 int n = 10; 4 void func(); 5 6 int main(){ 7 func(); 8 printf("main:%d\n".n); 9 return 0; 10 }
1 #include <stdio.h> 2 3 extern int n; 4 5 void func(){ 6 printf("module:%d\n",n); 7 }
在C语言中,const变量和普通变量是一样的,在其他源文件中也是可见的,可见范围是整个程序,在其他们文件中使用extern声明后就可以使用。在c++语言中,全局cosnt变量的作用域仍然是当前文件,但是它在其他文件中是不可见的,这和添加了static关键字的效果类似。所以可以放在头文件中,多次引入后也不会出错。
5.new和delete操作符
在c语言中,动态分配内存用malloc()函数,释放内存用free()函数
1 int *p = (int*) malloc( sizeof(int) * 10 ); //分配10个int型的内存空间 2 free(p); //释放内存
C++新增了new用来动态分配内存,delete用来释放内存。
1 int *p = new int; //分配1个int型的内存空间 2 delete p; //释放内存
new操作符会根据后面的数据类型来判断所需空间的大小
如果希望分配一组连续的数据,可以使用 new[]:
int *p = new int[10]; //分配10个int型的内存空间 delete[] p;
用 new[] 分配的内存需要用 delete[] 释放,它们是一一对应的。
6.inline内联函数
函数调用是有时间和空间开销的,程序在执行一个函数之前需要做一些准备工作,需要将实参、局部变量、返回地址以及若干寄存器都压入栈中,然后才能执行函数体中的代码,为了消除函数调用的时空开销,C++提供了一个提高效率的方法
即在编译时将函数调用处用函数体替换,在函数调用处直接嵌入函数体的函数称为内联函数。
指定内联函数的方法很简单,只需要在函数定义处增加inline关键字
1 #include <iostream> 2 using namespace std; 3 4 //内联函数,交换两个数的值 5 inline void swap(int *a, int *b){ 6 int temp; 7 temp = *a; 8 *a = *b; 9 *b = temp; 10 } 11 12 int main(){ 13 int m, n; 14 cin>>m>>n; 15 cout<<m<<", "<<n<<endl; 16 swap(&m, &n); 17 cout<<m<<", "<<n<<endl; 18 19 return 0; 20 }
一般使用内联函数替换带参数的宏。和宏一样,内联函数可以定义在头文件中,并且头文件被多次#include后也不会引发重复定义错误,内联函数在编译时会将函数调用处用函数体替换,编译完成后函数就不存在了,所以在链接时不会引发重复定义错误,且内联函数应该在函数定义放在本应该出现函数声明的地方。
7.默认参数
定义函数时可以给形参指定一个默认的值,这样调用函数时如果没有给这个形参赋值,那么就是用这个默认的值,调用函数时可以省略有默认值的参数。
C++规定,默认参数只能放在形参列表的最后,而且一旦为某个形参指定了默认值,那么它后面的所有形参都必须有默认值,不能再函数定义和声明中同时制定默认参数
C++规定,在给定的作用域中只能指定一次默认参数。而且在给定的作用域中一个形参只能被赋予一次默认参数,函数的后续声明只能为之前那些没有默认值的形参添加默认值,而且该形参右侧的所有形参必须都有默认值
8.重载
如果希望交换两个变量的值,这两个变量有多种类型,可以是int、float、char、bool等,我们需要哦他能够过参数把变量的地址传入函数内部,在C++中,C++允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载,借助重载,一个函数名可以有多种用途,参数列表又叫参数签名,包括参数的类型、参数的个数和参数的顺序,只要有一个不同就叫做参数列表不用。
1 #include <iostream> 2 using namespace std; 3 4 //交换 int 变量的值 5 void Swap(int *a, int *b){ 6 int temp = *a; 7 *a = *b; 8 *b = temp; 9 } 10 11 //交换 float 变量的值 12 void Swap(float *a, float *b){ 13 float temp = *a; 14 *a = *b; 15 *b = temp; 16 } 17 18 //交换 char 变量的值 19 void Swap(char *a, char *b){ 20 char temp = *a; 21 *a = *b; 22 *b = temp; 23 } 24 25 //交换 bool 变量的值 26 void Swap(bool *a, bool *b){ 27 char temp = *a; 28 *a = *b; 29 *b = temp; 30 } 31 32 int main(){ 33 //交换 int 变量的值 34 int n1 = 100, n2 = 200; 35 Swap(&n1, &n2); 36 cout<<n1<<", "<<n2<<endl; 37 38 //交换 float 变量的值 39 float f1 = 12.5, f2 = 56.93; 40 Swap(&f1, &f2); 41 cout<<f1<<", "<<f2<<endl; 42 43 //交换 char 变量的值 44 char c1 = 'A', c2 = 'B'; 45 Swap(&c1, &c2); 46 cout<<c1<<", "<<c2<<endl; 47 48 //交换 bool 变量的值 49 bool b1 = false, b2 = true; 50 Swap(&b1, &b2); 51 cout<<b1<<", "<<b2<<endl; 52 53 return 0; 54 }
而C++标准库中已经提供了交换两个变量的值的函数叫做swap,位于algorithm头文件中,为了避免和标准库中的swap冲突,特地将s大写。

浙公网安备 33010602011771号