C++比C多了什么(一)

1.1输入/输出流

流是字符集合或数据流的源或目的地
有两种流:
1) 输出流,在类库里称为ostream
2) 输入流,在类库里称为istream
同时处理输入和输出,由istream和ostream派生双向流iostream.
输入 输出
流 istream ostream
运算符 >> <<
预定义对象 cin cout
设备 键盘 显示器

1.2 引用

1.2.1 引用的作用
引用是用于给变量取别名
1.2.2 引用的定义的格式
数据类型 &别名 = 变量名;

比如:int a = 5;
int &b = a;

别名是变量名的引用,b是a的引用。
别名的引用对象是变量名,a是b的引用对象。
引用的对象是变量,不是常量,不能对常量进行引用!!!
& :引用声明符
数据类型:跟变量名的数据的类型是一样的
1.2.3 引用时需注意的问题

  1. 使用引用的时候必须要初始化,跟const关键字一样,在定义的同时必须初始化
  2. 引用一旦初始化,则固定引用,之后使用时,引用的目标不会发生改变
  3. 引用的本质:指针,指针的指向固定指向,----->指针常量
  4. 引用本身在系统占用一块内存空间,内存空间的大小一般固定为4个字节(指针所占的空间大小)(建立工程时一般选择了win32工程)
  5. 引用的空间实际是存储引用对象的地址,只是在打印引用的地址的时候显示是引用对象的地址
  6. 引用作为函数的参数传递

函数的参数传递的方式:
1)值传递:将实参的值传递给形参变量,形参改变不影响实参的变化
2)址传递:将实参以地址形式传递给形参变量(指针),形参指向的空间改变,实参指向的空间也会跟着变化
3)引用传递:效果跟址传递是一样,在C++中,能用指针作为函数的参数传递,基本都可以改为引用作为函数的参数
#include

using namespace std;

//值传递
//int x = a; int y = b;
void swap1(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}

//地址传递
//int *x = &a; int *y = &b;
void swap2(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}

//引用传递
//int &x = a; int &y = b;
void swap3(int &x, int &y)
{
int temp;
temp = x;
x = y;
y = temp;
}

int main(void)
{
int a,b;
a = 3, b = 5;
swap1(a,b);//1.值传递,形参改变但不影响实参
cout << "a = " << a << ", b = " << b << endl;

a = 3, b = 5;
swap2(&a, &b);//2.地址传递,形参改变,实参不变,但是实参指向空间变化
cout << "a = " << a << ", b = " << b << endl;

a = 3, b = 5;
swap3(a, b);//3.引用传递,形参改变,实参随之改变
cout << "a = " << a << ", b = " << b << endl;

}

从以上实验可以看出,在C++编程中,若需要通过函数对实参传入的变量进行赋值,可以使用引用传递参数的方法。

  1. 引用作为函数的返回值
    引用是引用目标变量的别名,操作引用,则就是在操作目标变量,当目标变量空间在栈区(局部变量),变量所在的函数结束,(栈区)空间被释放,目标变量的空间撤销,此时该目标变量的引用也会随着目标变量一起消失, 释放指针指向的空间的时候,指针最后要被置空,引用不需要这样的操作
    引用是与目标变量共存亡,引用在作为函数的返回值的时候,不能返回局部变量的引用(除了静态局部变量),局部变量会随着该变量所在的函数的结束而释放,此时返回局部变量的引用也是无用的

#include

using namespace std;

//值传递
//int x = a; int y = b;
void swap1(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}

//地址传递
//int *x = &a; int *y = &b;
void swap2(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}

//引用传递
//int &x = a; int &y = b;
void swap3(int &x, int &y)
{
int temp;
temp = x;
x = y;
y = temp;
}

int &f1(int a, int b)
{
b = a + b;
return b;
}

int &f2(int &a, int &b)
{
b = a + b;
return b;
}

int main(void)
{
int a,b;
a = 3, b = 5;

swap1(a,b);//1.值传递,形参改变但不影响实参
cout << "a = " << a << ", b = " << b << endl;

a = 3, b = 5;
swap2(&a, &b);//2.地址传递,形参改变,实参不变,但是实参指向空间变化
cout << "a = " << a << ", b = " << b << endl;

a = 3, b = 5;
swap3(a, b);//3.引用传递,形参改变,实参随之改变
cout << "a = " << a << ", b = " << b << endl;

int &c = f1(a, b);
cout << "c = " << c << endl;
cout << "a = " << a << ", b = " << b << endl;

int &d = f2(a, b);
cout << "d = " << d << endl;
cout << "a = " << a << ", b = " << b << endl;

}

  1. 引用具有的平行传递关系
    int a;
    int &b = a; //定义b为a的引用
    int &c = b; //定义c为b的引用,根据平行传递关系,c也是a的引用

总结:
a) 引用是对引用目标起别名,引用的对象必须是变量
b) 引用本质是指针,一旦初始化,则引用就固定指向,实际上是常量指针,在内存中所 占的空间大小一般为4个字节
c) 引用具有平行传递的关系
d) 引用一般作为函数的形参,比指针更方便,通俗
e) 引用如果作为函数的返回值,则不能返回局部变量的引用(非静态局部变量)
f) 引用会随着目标变量一起消失,目标变量空间释放,则引用也跟着消失
g) 引用不是创建变量,仅仅只是对目标变量起别名,操作别名就是在操作目标变量

1.3 const

1.3.1 功能
const关键字,只读关键字,修饰变量为只读变量
const 修饰变量必须要初始化!!!
const 修饰指针,const修饰谁,谁就是常量
一般用于修饰函数的形参
char * strcpy(char *str,const char *buf);

在C++中,const修饰成员变量------->只读成员
const 修饰成员函数------->只读成员函数

#include

const double f = 3.1415926535384;
const int a = 5;

using namespace std;

int main(void)
{
int a = 3;
int b = 4;
int c = 5;

const int *p1 = &a;
//const 修饰 *p1,*p1为常量
int const *p2 = &a;
//const 修饰 *p2,*p2为常量
int * const p3 = &a;
//const 修饰 p3,p3为常量,不能重新指向

p1 = &b;
//*p1 = 1;

p2 = &b;
//*p2 = 1;

//p3 = &b; 
*p3 = 1;

}

1.3.2 const作用

  1. 保护重要数据不被修改
  2. 用标识符替代一个常量,简化操作

1.4 函数的默认参数

1.4.1 函数的默认参数说明
在C++中定义函数时,可以设置形参的默认值,具体方法是在形参定义时进行初始化。
1.4.2 作用
在调用函数的时候,将经常使用的实参设置为函数的默认参数,则在调用函数的时候,如果实参跟设置的默认参数值是一样的,则可以不用传递实参,使用形参的默认值作为函数的实参。
简化调用函数时的操作。

1.4.3 注意
使用函数的默认参数的时候,需要注意实参的类型跟形参的类型一定要匹配
调用函数的时候,注意函数在传参的过程中是从左往右依次传参

1>. 写法:
函数的默认参数需要跟着函数的声明,函数的定义不能设置默认参数;除非函数的声明与定义在一体(此函数是在头文件与主函数之间定义)此时可以设置函数的默认参数
#include

using namespace std;
//在使用函数默认参数的前提下

//若函数定义和声明分离,声明时需要注明默认参数
int add(int a = 3, int b = 5);

//若函数定义和声明一体,则需要注明默认参数
int sub(int a = 10, int b = 7)
{
return (a - b);
}

int main(void)
{
cout << add() << endl;
cout << sub() << endl;
}

//若函数定义和声明分离,定义不能注明默认参数
int add(int a, int b)
{
return (a + b);
}

2>. 说明:

  1. 调用函数传参的时候,默认从左往右依次传递,
  2. 从函数的某一个参数设置默认值开始,后面所有的参数都需要有默认值
    #include

using namespace std;
//在使用函数默认参数的前提下

//错误,使用函数默认参数时,从出现默认值的参数起,
//后续参数都必须要用有默认参数
/int f1(int a = 10, int b)
{
return (a - b);
}
/

//正确,使用函数默认参数时,从出现默认值的参数起,
//后续参数都必须要用默认值
int f2(int a , int b = 7)
{
return (a - b);
}

int main(void)
{

}

1.5 内联函数(了解原理)

  1. 内联关键字:inline
  2. 内联函数的特点:缩短程序运行的时间,提高程序的运行效率
  3. 内联函数的用法:
    在函数的定义前面加inline关键字,表示建议系统将该函数声明为内联函数
    inline 函数返回值类型 函数名(参数列表)
    {
    //函数体
    }
  4. 程序在运行的时候,遇到内联函数,不会转去执行内联函数内部的程序,而是将内联函数的函数体直接嵌套在内联函数的调用的地方,缩短程序的运行时间,程序代码的体积也会相应的增大
  5. 内联函数的作用类似宏定义,内联函数本质是函数,具有函数的性质,但是不具有函数的结构
  6. 加inline关键字,仅仅表示建议将该函数声明为内联函数,具体是不是内联函数,需要系统决定,一般内联函数函数体代码不宜过长,一般1~5行;当内联的函数函数内部的代码过长,此时系统也会将该函数视为普通函数
  7. 内联函数的内部不能有循环语句,不能有开关语句(switch语句),递归函数不能成为内联函数
  8. 小代码的函数可以设置为内联函数
    //比如之前使用的格式转换函数dec就是采用内联函数方式定义
    inline ios_base& __CLRCALL_OR_CDECL dec(ios_base& _Iosbase)
    { // set basefield to dec
    _Iosbase.setf(ios_base::dec, ios_base::basefield);
    return (_Iosbase);
    }

猜你喜欢

转载自blog.csdn.net/qq_29011025/article/details/107144090