1. 命名空间
namespace:命名空间
using:声明;
1.1 命名空间的概念
如果在一个空间中,两个变量或函数的名字一样,编译的时候会冲突。命名空间就是为了解决C++中函数变量的命名冲突所采取的一种措施,能够解决多模块协同开发出现变量函数命名的冲突问题。
在这里面可以把命名空间理解成文件夹,如果你在hel1这个文件夹中编辑两个hello.cpp肯定会出问题,但是如果一个在hel1,一个在hel2这个文件夹中p,这个就不会出现冲突。
命名空间的必要性: 当程序比较大的时候,需要多人合作,命名空间就非常必要。
命名空间中可以有函数
1.2 命名空间的定义
命名空间用namespace定义,格式如下:
namespace 命名空间名
{
命名空间生命内容
}
例:
#include <iostream>
using namespace std;
namespace nsA
{
void print()
{
cout<<"nsA"<<endl;
}
}
namespace nsB
{
void print()
{
cout<<"nsB"<<endl;
}
}
int main()
{
nsA::print();
nsB::print();
return 0;
}
1.3 命名空间成员的使用
1.3.1 using 声明
using声明可以出现在全局域和任意命名空间中,也可以出现在局部域中。
using namespace_name::name;
一旦使用using声明,就可以直接引用命名空间中的成员,而不需要再引用该成员的命名空间。
命名空间std,这是最常用的命名空间,而不需要再引用该成员的命名空间。
#include <string>
#include <iostream>
using std::cin; //using声明,表明要引用标准库std中的成员cin;
using std::string; //using声明,表明要引用标准库std中的成员string;
int main()
{
string temp; //正确,string已经声明,可以直接使用
cin>>temp; //正确,cin已经声明,可以直接使用
cout<<temp; //错误,cout未声明,无法直接使用
std::cout<<temp; //正确,通过全名使用cout,
return 0;
}
在using 指令中,using后面必须跟关键字namespace,而且最后必须为命名空间名;如:
using namespace std;
在using 声明中,关键字后面没有namespace, 后面必须为命名空间的成员名。如:
using std::cin;
1.3.2 using的作用域
using的作用域用大括号括起来。
#include <iostream>
using namespace std;
namespace nsA{
int var = 12;
}
namespace nsB{
double var = 12.33;
}
int main()
{
{
using namespace nsA; //using指令,使用nsA
cout<<"nsA var="<<var<<endl;
}
{
using namespace nsB; //using指令,使用nsB
cout<<"nsB var="<<var<<endl;
}
return 0;
}
2.new ,delete
2.1. malloc,free
C语言中malloc ,free是在堆上申请、释放空间。
int* p = (int *)malloc(sizeof(int)*10);
free(p);
2.2. new,delete
C++中不仅可使用malloc,free。还有new,delete
int *p = new int; //申请单个类型空间
delete p
int *p = new int[10];//申请一串空间
delete[] p;
2.3. 区别
两组不能混用,必须成对出现。
区别:
1,malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
2,对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
3,因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。
4,C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。
5、new可以认为是malloc加构造函数的执行。new出来的指针是直接带类型信息的。而malloc返回的都是void指针。
3.inline 内联函数
函数调用的时候会发生一些时间开销:系统栈的保护,参数的传递,栈的恢复。 对于函数体比较小,执行时间短但频繁使用的函数来说,这种开销比较大。
内联函数机制,不是在函数调用的时候发生转移而是在编译的时候将函数体嵌入到每个内联函数调用处,可以省去调用进栈出栈的时间开销。
函数的定义:
inline <类型标识><函数名>(形参列表)
{
函数体
}
必要说明:
1) 内联函数不能含有循环语句,swtich语句
2) 内联函数必须在调用之前声明和定义;
3)内联函数不能指定抛出异常类型;
4)inline只是修饰函数向编译器提出内联请求,做不作为内联函数由编译器决定;
#include <iostream>
using namespace std;
inline int max(int,int);
int main()
{
int a[10];
cout<<"input 10 members:"<<endl;
for(i=0; i<10; i++)
{
cin>>a[i];
}
int temp=a[0];
for(i=0; i<10; i++)
{
temp = max(temp, a[i]);
}
cout<<"in 10 members is max :"<<temp<<endl;
return 0;
}
inline int max(int x,int y)
{
return x>=y>x:y;
}
内联函数的本质是使用空间来换时间,也就是说把内联函数的内码先加载到内存中,占据了一点内存空间。这样的好处是调用内联函数时执行效率非常快,省掉了调用普通函数保存现场、跳转、恢复现场的操作。
4. 函数的重载
C中,每个函数都必须有唯一的一个名字,这个就必须记住每一个函数的名字。
例如经常所见的求最大值的函数,数据类型不同,函数名不能相同。
int max1(int ,int);
int max2(int ,int, int);
double max3(double, double);
C++中允许同名函数存在,但函数的参数个数必须不同:即形参个数不同,或形参个数相同,但参数类型有所不同。—-这就是重载。
#include <iostream>
using namespace std;
int max(int,int);
double max(double,double);
int max(int,int,int);
int main()
{
int i=5, j=9, k=10, p=0;
double m=33.4, n=8.9, q=0;
p=max(i,j);
cout<<i<<","<<j<<"max in two"<<p<<endl;
p=max(i,j,k);
cout<<i<<","<<j<<","<<k<<"max in three"<<p<<endl;
q=max(m,n);
cout<<m<<","<<n<<"max in two"<<q<<endl;
return 0;
}
int max(int x,int y)
{
return x>y?x:y;
}
double max(double x,double y)
{
return x>y?x:y;
}
int max(int x,int y,int z)
{
int temp;
temp = x>y?x:y;
temp = temp>z?temp:z;
return temp;
}
5. 带默认值的函数
函数调用时,形参值是由实参数决定,形参实参必须相同。
C++还提供一种方法,为形参设置一个默认值,即形参不从实参取值。
5.1 函数的声明
默认值在函数声明中提供,但当有声明又有定义时,定义中不允许有默认值。
如果函数只有定义,则默认值可以出现在函数定义中。
#include <iostream>
using namespace std;
void point(int x,int y=0, int z=0)
{
cout<<"("<<x<<","<<y<<","<<z<<")"<<endl;
}
int main()
{
int x,y,z;
cout<<"X, Y,Z:"<<endl;
cin>>x>>y>>z;
point(x);
point(x,y);
point(x,y,z);
return 0;
}
5.2 带默认值的形参顺序规定
在函数中有多个默认参数,则形参从最右边依次向左设定。当调用函数时,只能向左匹配参数。
错误的表示:
void point(int=0,int, int=0);
void point(int=0,int=0,int);
调用时,若不赋值则使用默认值,若赋值则覆盖默认值:
point(x); ok
point(x,y);ok
point(x,y,z);ok
point(); error
point(x, , z); error
5.3 默认参数与函数重载
使用带默认值的函数可以将一些简单的函数合并为一个函数。但是一个函数不能既作为重载函数,又作为带默认值的函数。会出现二义性,系统无法执行。
例:
point(int x,int y);
point(int x,int y=0, int z=0);
point(x,y);
5.4 默认值的限定
默认值:可以是全局变量,全局常量,也可以作为一个函数表达式。默认值不能是局部变量。
6. 标准输入/输出
最常用的输入输出运算符>>, <<
头文件 : #include <iostream>
1) cin : 标准输入的istream类对象,使用户能够从终端读数据,默认是键值;
2)cout:标准输出的ostream类对象,使用户从终端写数据,默认是屏幕;
3)cerr:标准错误的ostream, cerr输出程序错误,默认是屏幕
6.1 输入操作符>>
输入主要由右移操作符>>,cin组成:
#include <iostream> //标准输入输出头文件
#include <string> //字符串函数头文件
using namespace std; //标准命名空间
void main()
{
int i;
while ( cin>>i ) //循环输入整数i
; //空语句
}
6.2 输出操作符<<
cout,<<
cout << "hello world!\n";
例:
#include <iostream> //标准输入输出头文件
#include <string> //字符串函数头文件
using namespace std; //标准命名空间
void main()
{
cout<<"字符串\"abc\" 的长度是: \n"; //输出字符串
cout<<strlen("abc"); //函数
cout<<endl;
}
#include <iostream> //标准输入输出头文件
#include <string> //字符串函数头文件
using namespace std; //标准命名空间
void main()
{
string s;
char *p="abc"; //字符指针
int i;
cout<<"Hello World"<<endl;
cin>>i; //输入i值
cout<<"i=\t"<<i<<endl; //表达式中的“\t”表示横向跳格
cout<<p<<endl; //输入字符指针p所指向的字符串
cin>>s;
if (s.empty()==true) //判断输入字符串是否为空,如果是空的,则返回true,否则返回false
cerr<<"string s is empty"<<endl;
}
6.3 字符串操作
可以按照C中字符数组的形式读取字符串,也可以用string类型读取字符串。
使用string类型的好处是字符串相关的内存可以被自动管理,C中字符串首先要声明足够大的存储空间才能读入字符串。
string易于管理。
#include <iostream>
#include <string>
using namespace std;
void main()
{
string str; //定义字符串类型变量
cin>>str; //输入字符串,回车为结束标志
cout<<str<<endl; //输出
}