头文件
#include <>或#include ""
<>
强制类型转换
double a=1.6;
cout<<static_cast<int>(a)<<endl;
输出为1
注意旧的强制类型转换为int(a),这比新的更容易出错,得不到想要的结果,所以推荐static_cast<转换成的类型>()
自动判断数据类型
auto n=16;
自动判断n的类型为int
const auto e=1.1;
自动判断静态常数e的类型为double
查看数据类型
#include <typeinfo>
double a=1.1; float b=2.2f;
cout<<typeid(a*b).name()<<endl;
输出为double
按位运算符
& 按位与 | 按位或 ^ 按位异或 ~ 按位取反 >>右移 <<左移
屏蔽高四位:
char letter=‘A‘;
letter &=0x0F;
在占用中间存储空间的情况下交换两个整数:
char a=‘a‘,b=‘b‘;
a=a^b;
b=a^b;
a=a^b;
结果a=‘b‘,b=‘a‘
移位:
int a=40;
cout<<(a<<2)<<(a>>2)<<endl;
结果:160 10
注意精度损失和符号位会保留
lvalue和rvalue
lvalue:内存中持续存储数据的一个地址,因为lvalue的表达式都可以放在“=”左边,所以叫lvalue
rvalue:临时存储的表达式结果
a=b+c; //b+c的结果临时存在内存中,并复制给a,然后丢弃,所以b+c为rvalue
++a; //结果为递增之后的a,所以为lvalue
a++; //将a的值临时存储为表达式,然后才递增a,所以为rvalue
存储时间和作用域
作用域:可以访问该变量的程序代码域
存储时间:创建到销毁变量,释放占用空间的期间
1.自动存储时间:具有局部作用域或者代码块作用域,空间在内存栈中自动分配,如果没有初始化那么将为当前分配到内存空间的无用值
2.静态存储时间:如全局变量(在main函数之前声明,如未赋予初值则为0),如果因为局部变量而被隐藏,可以使用如::a显示全局变量而不管被隐藏多深
3.动态存储时间
静态变量:在一个代码块内声明,并且只能在代码块内部使用它,但是在程序生存期内持续存在,如果没有赋予初值则为0
名称空间
用于防止将相同的名称用于不同的函数,即防止意外的名称冲突
ISO/IEC C++标准库中使用的所有名称都在std名称空间中定义
using声明:using std::cout,这样之后的cout就相当于std::cout
using指令:using namespace std,将来自std名称空间的所有名称导入源文件,使用标准库的名称都不用打std,但是也否定了使用名称空间的主要原因——防止意外的名称冲突
声明名称空间:namespace 名称空间名{变量或者函数},调用为名称空间::变量或者函数,main()不能放在名称空间中
C++/CLI编程
一种基本类型是值类类型,既可以表现为普通的值,也可以在环境需要时表现为对象
封箱:编译器安排从原值到关联的值类类型对象的自动转换
拆箱:和封箱相反
ISO/IEC C++基本类型名称是C++/CLI程序中值类型名称的别名,所以可以使用(比如bool为System::Boolen的别名,int为System::Int32的别名)
在ISO/IEC C++中,基本类型和类类型完全不同,但是C++/CLI中,所有数据都是作为类类型的对象储存的,或者作为值类类型,或者作为引用类类型
main(array<System::String ^> ^args)的()中的内容作用是从命令行启动程序的执行时把值传递到函数main()
格式化输出:
System::Int32 a = 1;
double b=1.2;
Console::WriteLine(L"a is {0},b is {1,-6:F2}",a,b);
结果:a is 1,b is 1.20
Console::WriteLine(L"a is {0},b is {1,-6:F2}",a,b);等同于Console::Write(L"a is ");Console::Write(a);Console::Write(L",b is ");Console::Write(b);
L表明这是一个宽字符串,每个字符张两个字节
{n,w:Axx}
1.n为参数的位置,这里a为参数0,b为参数1
2.w为可选的字段宽度规范,正数为右对齐,负数为左对齐,如果显示字段小于规定宽度则用空格补全,如果大于则忽略字段宽度规范
3.A规定如何对值进行格式化,这里F为规定精度
4.xx为可选的一个或两个数字
WriteLine()和Write()都是Console类的函数,唯一的区别就是WriteLine()最后有一个默认的换行
A:
D或d 输出整数时如果精度大于位数则在左边填充0
E或e 科学计数法输出,精度为小数位
F或f 浮点数输出,精度为小数位
读取:
String^ line=Console::ReadLine();
char ch=Console::Read();
ConsoleKeyInfo keypress=Console::ReadKey(true);
注:Console::ReadKey()函数把按下的键作为ConsoleKeyInfo类型的对象返回,其中keypress.KeyChar存储返回的值,true表示按下的内容不再屏幕显示,而默认或者false则显示;打印:
Console::WriteLine(L"you enter {0}",keypress.KeyChar);
int value=Int32::Parse(Console::ReadLine());
注:Console::ReadLine()函数返回的字符串被作为参数传递给Int32类的Parse()函数,Parse()将字符串转换为32位整数,如果要转换为double则用Double::Parse()
强制转换:
double a=1.2;
double b=2.7;
int c= safe_cast<int>(a)+safe_cast<int>(b);
注:safe_cast和本地C++编程的static_cast用法一样
枚举:
enum class Fruit{Apple=1,Banana,Orange};
Fruit fruit=Fruit::Apple;
Console::WriteLine(L"Fruit is {0} and the value is {1}",fruit,safe_cast<int>(fruit));
结果:Fruit is Apple and the value is 1
注:C++/CLI枚举是一种类类型,Fruit相当于类,Apple和Banana相当于类的对象而不是ISO/IEC C++中那样只是基本类型的值,因此C++/CLI的枚举不能放在函数中,必须全局(在main之前)
::为作用域运算符,表示Apple和Banana在Fruit作用域内
如果没给枚举对象赋值那么第一个默认为0,也可以给枚举对象赋其它类型的值,比如bool,long,short
枚举的运算:
Fruit fruit1=Fruit::Apple;
Fruit fruit2=Fruit::Orange;
Fruit fruit3=fruit2-fruit1;
Fruit fruit4=fruit2-safe_cast<Fruit>(fruit1);
Fruit fruit5=fruit2-Fruit::Apple;
Console::WriteLine(L"fruit3 is {0},fruit4 is {1},fruit5 is {2}",fruit3,fruit4,fruit5);
注:如fruit6=fruit2-2;为错误,因为没有自动转换
枚举作为标志:
[Flags] enum class Flag{Read=1,Write=2,Execute=4,None=8};
Flag statue=Flag::Read | Flag::Write | Flag::Execute;
//statue变量的值为0000 0000 0000 0000 0000 0000 0000 1011
Console::WriteLine(L"statue is {0}",statue);
statue=statue & ~Flag::Write;
//statue变量的值为0000 0000 0000 0000 0000 0000 0000 1001
Console::WriteLine(L"statue is {0}",statue);
结果:
statue is Read Write Execute
statue is Read Execute
注:statue=statue & Flag::Write不能写成statue &=Flag::Write;可以在C++/CLI使用和本地C++相同的枚举,但是不推荐
查看类型:
int a=5;
double b=2.3;
Console::WriteLine(L"Type of a*b is {0}",(a*b).GetType());
结果:Type of a*b is System.Double
注:本地C++的typeid操作不能用在C++/CLI中;(a*b).GetType()会产生一个System::Type的一个对象,输出的时候会自动转换为System::String的对象
第二章 数据,变量和计算