c++数据类型
1.1对c数据类型的拓展
基本数据类型:
char | unsigned char | int |
---|---|---|
short | unsigned short | long |
unsigned long | float | double |
long double |
与C语言相比,拓展了bool
类型,对结构体、联合、枚举做了改进。
1.1.1 结构体
-
c++中定义结构型变量,可以省略struct 关键字。
-
c++结构体中可以直接定义函数,称之为 成员函数(方法)。
#include <iostream> #include <cstring> using namespace std; int main(void) { struct stu { int age; char name[20]; void who(void) { cout << "My name is " << name << " . I am " << age <<" years old this year" << endl; } }; stu s1; s1.age = 24; strcpy(s1.name, "Rose"); s1.who(); return 0; }
1.1.2 联合
-
c++中定义联合体变量,可以省略
union
关键字。union xx {........}; xx x;//定义联合体变量可以省略union关键字
-
支持匿名联合(成员当做局部变量)
union{//没有名字 ......... };
#include <iostream> using namespace std; int main(void) { union{ //匿名联合 int num; char c[4]; }; num = 0x12345678; cout << hex << (int)c[0] << " " << (int)c[1] << endl; return 0; }
1.1.3 枚举
-
c++中定义枚举变量,可以省略
enum
关键字 -
c++中枚举是独立的数据类型, 不能当做整型数使用。
#include <iostream> using namespace std; int main(void) { enum COLOR{red, white, black}; COLOR a = white; //a = 2; //error: invalid conversion from ‘int’ to ‘main()::COLOR’ [-fpermissive] cout << a << endl; return 0; }
1.1.4 布尔类型
C++中布尔(bool)是基本数据类型,专门表示逻辑值
布尔类型的字面值常量:
true 表示逻辑真
false表示逻辑假
布尔类型的本质: 单字节的整数,使用1表示真,0表示假
任何基本类型都可以被隐式转换为布尔类型
#include <iostream>
using namespace std;
int main(void)
{
bool a = true;
cout << a << endl;
cout << boolalpha << a << endl;
a = 3 + 5;
cout << boolalpha << a << endl;
return 0;
}
*********
1
true
true
1.1.5 字符串
-
C++兼容C中的字符串表示方法和操作函数
-
C++专门设计了string类型表示字符串
-
string类型字符串定义
string s; //定义空字符串 string s("hello"); string s = "hello"; string s = string("hello");
-
字符串拷贝
string s1 = “hello”; string s2 = s1;
-
字符串连接
string s1 = “hello”, s2 = “ world”; string s3 = s1 + s2;//s3:hello world s1 += s2;//s1:hello world
-
字符串比较
string s1 = “hello”, s2 = “ world”; if(s1 == s2){ cout << “true”<< endl; } if(s1 != s2){ cout << “false”<< endl; }
-
随机访问
string s = “hello”; s[0] =“H”; //Hello
-
获取字符串长度
size_t size(); size_t length();
-
转换为C风格的字符串
const char* c_str();
-
字符串交换
void swap(string s1,string s2)
-
-
示例代码
#include <iostream>
#include <cstdio>
using namespace std;
int main(){
/*定义*/
string s1; //定义空字符串
string s2("aaa");
string s3 = string("bbb");
string s4 = "cccc";
/*字符串的拷贝*/
string s5 = s2; // char *p5 = p2;
cout << "s5 = " << s5 << endl;
/*拼接*/
s5 += s3;
cout << "s5 = " << s5 << endl;
/*字符串比较*/
if(s2 == s3){ //strcmp(.....)
cout << "true" << endl;
}
else
cout << "false" << endl;
/*取字符串长度*/
cout << "s5 length = "<< s5.length() << endl;
cout << "s5 length = "<< s5.size() << endl;
/*转换为C风格字符串*/
const char *p = s5.c_str();
printf("%s\n", p);
/*交换*/
swap(s2, s3);
cout << "s2= "<< s2 << " s3= "<< s3<< endl;
return 0;
}
*******************
s5 = aaa
s5 = aaabbb
false
s5 length = 6
s5 length = 6
aaabbb
s2= bbb s3= aaa
1.2 类型转换
类型转换分为隐式转换和显示转换。
写C/C++代码的时候,有时候不可避免的会使用类型转换,良好的编码风格中应该避免隐式转换,隐式转换有时候会产生不易察觉的问题。
1.2.1 隐式类型转换
C++定义了一套标准数据类型转换的规则,在必要时C++会用这套转换规则进行数据类型的转换。这种转换是在程序员不参与的情况下自动进行的,所以成为隐式类型转换。转换原则:
以下四种常见类型会发生隐式类型转换
-
多种数据类型的算术表达式中
int a = 2; float b = 3.4; double d = 2.2; a+b+c;
-
将一种数据类型赋值给另外一种数据类型变量
int a = 2; float b = 3.4; long double d = 2.2; b = a; d = a;
-
函数调用时,若实参表达式与形参的类型不相符
int Min(int a, int b){ return a<b?a:b; } int a = 2; float b= 3.4; int x = Min(b, a+3.5);
-
函数返回时,如果返回表达式的值与函数返回类型不同
double add(int a, int b){ return a+b; }
1.2.2 显示类型转换
static_cast | reinterpret_cast | const_cast | dynamic_cast
显示类型转换也称为强制类型转换,是指把一种数据类型强制转换为指定的另一种数据类型
int a = 4;
float c = (float) a; //C风格 c++也支持
float d = float(a); //C++风格 C不支持
C++ 提供了更严格的类型转换,可以提供更好的控制转换过程,C++增加了四个强制转换运算符: static_cast, dynamic_cast, const_cast和reinterpret_cast.
使用格式:目标类型变量 = xxxx_cast <目标类型>(源类型变量)
-
静态类型转换
static_cast
-
用于隐式转换的逆转换,常用于基本数据类型之间的转换,
void *
转换为其他类型的指针 -
不能用于整型和指针之间的相互转化,不能用于不同类型的指针、引用之间的转换(风险高)
-
用于自定义类型的转换(向上造型)
-
#include <iostream>
using namespace std;
int main(void)
{
int a = 100;
double a1 = (double)a;//c风格
double a2 = double(a);//c++风格
double b = static_cast<double>(a);
printf("%lf\n",b); //100.000000
void *p = malloc(100);
int *pi = static_cast<int *>(p);
char *pc = static_cast<char *>(p);
//int num = static_cast<int>(p); //不能用于整形和指针之间的互相转化
//pi = static_cast<int *>(pc); //不能用于不同类型的指针之间的转换
return 0;
}
- 重解释类型转换
reinterpret_cast
- 用于任意类型指针或引用之间的转换
- 指针和整型数之间的转换
#include <iostream>
using namespace std;
int main(void)
{
int a = 100;
double a1 = (double)a;//c风格
double a2 = double(a);//c++风格
double b = static_cast<double>(a);
printf("%lf\n",b); //100.000000
void *p = malloc(100);
int *pi = static_cast<int *>(p);
char *pc = static_cast<char *>(p);
//int num = static_cast<int>(p); //不能用于整形和指针之间的互相转化
//pi = static_cast<int *>(pc); //不能用于不同类型的指针之间的转换
int num = reinterpret_cast<long int>(p);
pi = reinterpret_cast<int *>(pc);
int n = 0x00414243;
char *ps = reinterpret_cast<char *>(&n);
cout << ps << endl; //CBA
cout << hex << n << endl ; //414243
return 0;
}
- 常类型转换
const_cast
- 用于去除指针或引用的常属性
#include <iostream>
using namespace std;
int main(void){
int tmp = 123;
const int *p1 = &tmp; //不能通过指针修改tmp对应的值
//(*p1)++; //error
int *p2 = const_cast<int *>(p1);//去除常属性
*p2 = 10000;
cout << tmp << endl;
return 0;
}
- 动态类型转换
dynamic_cast
- 主要用于多态中类指针的向下转型,可以检测是否可以转型成功
1.3 引用
c++出现了新的概念:引用。引用是某个对象的别名。
语法格式: 类型 &引用名 = 变量名
#include <iostream>
using namespace std;
int main(void)
{
int i = 10;
int &Ir = i; //给变量i取别名Ir
cout << "i= " << i << endl;
cout << "Ir= " << Ir << endl;
cout << "i的地址: " << &i << endl;
cout << "Ir的地址: " << &Ir << endl;
return 0;
}
******************************
i= 10 **
Ir= 10 **
i的地址: 0x7ffcb5a41e0c **
Ir的地址: 0x7ffcb5a41e0c ***
******************************
可以看出i和Ir是同一块内存。
用途
- 简化编程,用指针的场景可以引用替换(尽量减少指针的使用)
- 系统开销更小
#include <iostream>
using namespace std;
void swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void swap2(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
struct stu{
char name[20];
int age;
int id;//20+4+4=28
};
void func(struct stu s1){
}
void func2(struct stu &s1){
}
int main(void)
{
int x = 34;
int y = 56;
//swap(&x, &y);//正常交换
swap2(x, y);//使用引用
cout << "x= "<< x << "\t" << "y= " << y << endl;
stu st;
func(st);//声明的时候使用28字节,调用时还使用28字节。共使用48字节
func2(st);//使用引用一共只使用28字节。
// int &r1 = 100;右值引用
// <==> int *const r1 = 100; r1的值应该是可以被改的,显然100不能被改
//error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’
const int &r1 = 100;//ok 常引用 万能引用
const int &r2 = x;//ok
return 0;
}
在使用引用时需要注意以下几个问题:
- &的位置是灵活的,以下几种定义完全相同
int& ir = i;
int & ir = i;
int &ir = i;
- 在变量声明时出现&才是引用运算符(包括函数参数声明和函数返回类型的声明
int &ir =i;
int &f(int &i1, int &);
- 引用必须定义时初始化
float f;
float &r1 = f;
float &r2;
r2 = f; //错误
-
const引用(常引用)。在定义引用时一般为左值(变量)。
左值,是指变量对应的那块内存区域,是可以放在赋值符号左边的值;
右值,是指变量对应的内存区域中存储的数据值,是可以“放在赋值符号右边的值”。
常量、表达式都是右值,例如:
int i = 1;
i = i+10;
i+10 = i;//错误
i=10;
10=i; //错误
可以使用const进行限制,使他成为不允许被修改的常量引用。
int &i = 3; //错误 int *consti = 3 错误的
const int &i = 3;// 正确
int a = 100;
char &c = a; //错误 将a转换char类型,转换结果保存到临时变量中 实际引用临时变量,而临时变量是右值
-
引用的本质
引用的本质就是指针常量。
//int *const x = &m; int *const y= &n
void swap(int &x, int &y){
int tmp = 0;
tmp = x; //tmp = *x;
x = y; // *x = * y;
y = tmp; // *y = tmp
}
int main(void){
int m = 10, n = 20;
swap(m, n);
return 0;
}
内存区域中存储的数据值,是可以“放在赋值符号右边的值”。
常量、表达式都是右值,例如:
int i = 1;
i = i+10;
i+10 = i;//错误
i=10;
10=i; //错误
可以使用const进行限制,使他成为不允许被修改的常量引用。
int &i = 3; //错误 int *consti = 3 错误的
const int &i = 3;// 正确
int a = 100;
char &c = a; //错误 将a转换char类型,转换结果保存到临时变量中 实际引用临时变量,而临时变量是右值
-
引用的本质
引用的本质就是指针常量。
//int *const x = &m; int *const y= &n
void swap(int &x, int &y){
int tmp = 0;
tmp = x; //tmp = *x;
x = y; // *x = * y;
y = tmp; // *y = tmp
}
int main(void){
int m = 10, n = 20;
swap(m, n);
return 0;
}