面向对象第三讲
1.输入与输出
#include <iostream>
using namespace std;
int main()
{
int num;
char ch;
double d;
char src[100];
//cin:对象(变量) >> 输入流
cin >> num;
cin >> ch;
cin >> d;
//cin >> src;
cin.get();//getchar
cin.getline( src , 100 - 1 );
//cout:对象(变量) << 输出流
cout << "num = " << num << endl;
cout << "ch = " << ch << endl;
cout << "c = " << c << endl;
cout << "src = " << src << endl;
return 0;
}
cin的作用是标注输入流,cout的作用是标注输出流。
作用相当于scanf和printf。
if(5 != num)
{
cerr << "num != 5" << endl;
}
输入正常打印信息用cout,异常打印信息用cerr。
#include <iostream>
using namespace std;
int main()
{
cout << "hello world";
//cout是有缓冲区的,类型是行缓冲
while(1);
return 0;
}
该代码运行陷入死循环,且hello world不会显示出结果。但将cout换成cerr或clog,会打印出hello world.
2.C++对C的实用性加强
for(int i = 0;i < 100;i++)
//for 语句的升级,解决循环变量浪费空间的问题。
C89还不允许这种写法,直到C99才出现。
//新类型:bool 提高可读性
bool flag = false;
while (flag = =true)
//条件表达式:可以将返回值作为左值
int a;
int b;
int max = a > b ? a : b;
a > b ? a :b = 10;
cout << "b = " << b << endl;
关键字的升级:static,const,register,extern,typedef,inline
register 关键字的升级
将修饰变量尽可能的保存到CPU内部寄存器中,从而省去了内存抓取数据的时间,提高程序运行效率。
注:
1.register只能修饰局部变量,不能修饰函数和全局变量
2.register修饰的变量,不能再用&获取该变量的地址(register修饰的变量在CPU内部寄存器中,如果对其取址,register对变量的声明会变得无效,被定义的变量将会强制存放在内存中)
错误范例:
register int num = 6;
int *p = #
3.regisrer修饰的变量,一定是CPU所接受的数据类型
使用场景: 频繁访问的变量
const 关键字的升级
const修饰的变量就是常量。const会被编译器放到符号表中,编译器不会为const常量分配空间,除非对const常量取地址或进行extern操作时,编译器才会为其分配空间。
int count = 5;
const int *p = &count;//const修饰指针,不能通过该指针修改指向内存空间的值
注: const指针对const指针
使用场景: 修饰函数形参(保证函数实参在函数执行过程中不被修改)
typedef 关键字的升级
启用新的关键字using
给数据类型重命名,提高代码可读性、移植性、编程效率
typedef int MAX-num;
typedef unsigned char uChar;
MAX_num aa;
MAX_num bb;
uChar ch = -128;
通过typedef可以使你的代码不易被别人看懂。
函数名:指针常量 保存函数的入口地址
//typedef int (*p_FUNC)(int ,int);
using P_FUNC = int (* )(int , int);
//int (*p_func ) = (int , int)//函数指针变量
P_FUNC p_func = add;
//P_FUNC;
auto 关键字
C语言: 自动变量(所在函数结束之后释放空间)
C++: 类型推导,高效编程
auto p = 5;
auto p1 = 'a';
auto p2 = "hello world";
auto p_func = add;
auto能够自动推断变量的类型,通过变量的初始值或表达式中参与运算的数据类型来推断变量的类型。
传值&传地址
传实参变量名,只能使用实参的值,不能修改;传实参变量的地址,既能使用也能修改。
当需要修改实参变量的值,传实参变量的地址;当只使用实参变量的值,传实参变量名。
void swap(int *a , int *b )
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int a = 5;
int b = 6;
swap(&a , &b);
printf("a = %d , b = %d",a , b);
return 0;
}
程序运行结果
a = 6 , b = 5
引用
给变量起别名,操作别名就相当于操作这个变量。
#include <iostream>
using namespace std;
int main()
{
int a = 5;
int b = 6;
int &r_a = a;//r_a引用(定义必须初始化)
int &r_b = b;
r_a++;
r_b++;
cout << a << endl;
cout << b << endl;
return 0;
}
程序运行结果
6
7
使用场景: 函数形参、返回值(函数调用可以作为左值)
const int &ref = 5;//常引用(绑定常量)
左值引用&右值引用
左值引用: 能够修改、取地址(只能绑定左值)
右值引用: 不能修改、取地址(对象移动,只能绑定右值)
int num =5;
int &l_num = num;
int &&r_num = 5;
int &&r_num2 = std::move(num);//std::move(num)可以将左值转换成右值
r_num++;
cout << "r_num = " << r_num << endl;
引用&指针
1.指针是变量,引用是别名,引用解决函数传参传地址选择问题
2.指针占用内存空间,引用实际上也占用内存空间(编译阶段确定,并且隐藏)
3.指针有多级指针,引用有左值引用与右值引用
4.指针不安全,容易造成内存泄漏,引用则不会
malloc &new free & delete
1.\malloc/free 函数 new /delect 运算符
2.\malloc/free按照字节为单位分配,new/delect按照类型为单位
3.\malloc/free不能初始化分配空间,new/delect可以初始化
扩展: 如何给多维数组分配空间?
扩展: 传一维数组名,二维数组名,三维数组名,函数形参如何定义?
3.C++对C的函数扩展
inline内嵌
作用: 内存空间换运行时间,提高运行效率(只能修饰函数)
即: 时间(编译)换空间(内存) 空间(内存)换时间(运行)
#include <iostream>
using namespace std;
#define MAX(a ,b) a > b ? a : b
int max ( int a ,int b)
{
return a > b ? a : b;
}
int main()
{
int a = 5;
int b = 6;
int max_num = MAX(a , b);//宏函数(省去函数传参、返回、释放等一系列操作)
int max_num2 = max(a ,b);//自定义函数(形参需要分配空间)
return 0;
}
用inline代替
#include <iostream>
using namespace std;
inline max ( int a ,int b)
{
return a > b ? a : b;
}
int main()
{
int a = 5;
int b = 6;
max(a ,b);
return 0;
}
默认参数
默认参数的右边必须也是默认参数。
#include <iostream>
using namespace std;
int add ( int a = 6, b = 7; c = 8);
{
return a + b;
}
int main()
{
cout << add (6 ,7) << endl;
cout << add (6 , 7 , 8) << endl;
cout << add (6) << endl;
return 0;
}