c++数据类型、类型转换以及引用

c++数据类型

1.1对c数据类型的拓展

基本数据类型:

charunsigned charint
shortunsigned shortlong
unsigned longfloatdouble
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类型表示字符串

    1. string类型字符串定义

      string s; //定义空字符串
      string s("hello");
      string s = "hello";
      string s = string("hello");
      
    2. 字符串拷贝

      string s1 = “hello”;
      string s2 = s1;
      
    3. 字符串连接

      string s1 = “hello”, s2 = “ world”;
      string s3 = s1 + s2;//s3:hello world
      s1 += s2;//s1:hello world
      
    4. 字符串比较

      string s1 = “hello”, s2 = “ world”;
      if(s1 == s2){ cout << “true”<< endl; }
      if(s1 != s2){ cout << “false”<< endl; }
      
    5. 随机访问

      string s = “hello”;
      s[0] =“H”; //Hello
      
    6. 获取字符串长度

      size_t size();
      size_t length();
      
    7. 转换为C风格的字符串

      const char* c_str();
      
    8. 字符串交换

      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	***
******************************

可以看出iIr是同一块内存。

用途

  1. 简化编程,用指针的场景可以引用替换(尽量减少指针的使用)
  2. 系统开销更小
#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;
}
  • 18
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值