C++学习二

复合类型

C++除了之前提到的基本数据类型还包括复合类型,如数组,结构体,指针

数组

声明一个数组需要具备三点:元素类型,元素个数,数组名

int a[6]={1,2,3,4,5,6};//下表注意从0开始,从左到右是a[0],a[1],a[2],a[3],a[4],a[5]
int n;
cin>>n;
int*a=new int[n];//用new 关键字动态创建数组,优势之一是大小可变化,6用变量n代替,此时值为随机值,如果后面带(),则初始化为0

在这里插入图片描述
注1:使用数组过程中千万注意不要越界访问**
注2:计算数组长度的一个小技巧,int length=sizeof(数组名)/sizeof(元素类型)

字符串

C++沿袭了C语言风格的字符串,同时自己又衍生出新的字符串string

char str[7]="abcdef";//str={'a','b','c','d','e','f','\0'},显然空字符‘\0’包含在内
char*str="abcdef";//c风格字符串,和上面写法不一样,本质一样
string str="abcdef";//C++风格字符串

在这里插入图片描述
注1:字符串用双引号表示,字符用单引号表示
注2:字符串数组计算大小时,最后一个位置要留给空字符’\0’,但是计算长度时,空字符不包含在里面

字符串输入

cin一般以空格,制表,换行为结束标志,也就是说cin只接受一个单词。如果要接受一长串字符包括空格,那么需要用到getline。

#include<iostream>
#include<string>

using namespace std;
int main()
{
	
	string str = "";//定义一个字符串变量,初始化为空
	cin >> str;//输入字符串abcd hdjksdl  注意中间有一个空格
	cout << str << endl;//打印abcd,后面的空格没有被接收
	getline(cin, str);接收 hdjksdl,空格被接收了
	cout << str << endl;//打印 hdjksdl,前面有一个空格
	return 0;
}

还有cin.get(),cin.getline(),都是针对C风格的字符数组的,不适用于string类型,多说一句,cin.get()可以用来读取一行数据,它的特点是遇到换行就停止,但同时,换行符会被保留在缓存区,所以需要额外调用一次cin.get()来丢弃换行符

字符串拷贝,拼接
string str="abd";
string str1=str;//str1="abd"
string str2=str1+str;//str2="abdabd"
int len=str2.size();//len=6
结构

在这里插入图片描述
结构体说白了就是一个大仓库,啥东西都往里面放,这个仓库有多大(内存),就看所有东西加起来有多少(内存)。

struct student
{
	char sex;
	int schoolnumber;
	int score;
}s;//定义一个student对象s
//s={ 'M', 12345, 16 };对s进行初始化

那么怎么访问这个结构里面的成员呢?(s.name就是访问姓名,s.schoolnumber就是访问学号等等)再问一个问题就是这个结构到底多大?是9个字节吗?(答案是12字节,奥秘就在字节对齐,有兴趣可以自行百度)

结构数组

由于结构也是一种数据类型,因此把它作为数组元素也是可以的,一切类型皆原子,你也可以把数组当成数组元素放在一个数组里面,那就是二维数组啦。

联合体

和结构体不同,联合体有很多成员,但是一次只能放一种成员

枚举

枚举类型(enumeration)是C++中的一种派生数据类型,它是由用户定义的若干枚举常量的集合。

如果一个变量只有几种可能的值,可以定义为枚举(enumeration)类型。所谓"枚举"是指将变量的值一一列举出来,变量的值只能在列举出来的值的范围内。默认情况下,第一个名称的值为 0,第二个名称的值为 1,第三个名称的值为 2,以此类推。但是,您也可以给名称赋予一个特殊的值,只需要添加一个初始值即可,创建枚举,需要使用关键字 enum。枚举类型的一般形式为:

enum 枚举名{ 
     标识符[=整型常数], 
     标识符[=整型常数], 
... 
    标识符[=整型常数]
} 枚举变量;
   
指针,数组,指针运算,解引用
int a=5;
int* p=&a;//声明一个指针p,把变量a的地址赋值给p
cout<<*p<<endl;//解引用p指针,打印a的值,也就是5
int*q=new int();//动态申请一个内存空间,把指针q指向它,系统会自动为该内存空间分配一个值为0
delete q;

:用new创建的指针,使用完毕之后要用delete删除,否则不断申请内存,又不及时释放,会导致内存泄漏
在C++中,数组名也就是一个指向首元素地址的一个指针常量。而指针加减操作是以储存的元素的类型所占字节数为单位,对于整型,加一则向后移动4个字节,减一则向前移动4个字节。这也是数组为什么可以用下标访问元素的原因,底层使用指针的加减运算来实现间接访问的。

    int a[10];
	cout << a << endl;//display &a[0]
	cout << &a << endl;//display address of whole array
	cout <<&a[0]<<endl;//display &a[0]

这三个在值上是相等的,但是从概念角度是不一样的。

数组的动态联编,静态联编

很简单,直接在编译器就能确定数组长度,比如int a[10]={1,2,3}就是静态联编,而要采用new关键词进行动态创建数组就是动态联编,因为这时候数组的长度要在运行的时候才能被确定。

字符串的地址

用一个字符串初始化指针,比如char*p=“abc”,左边是指针类型,存放的是地址值,而右边是一个字符串,既然这两者可以划等号就说明右边这个字符串其实代表的就是一个地址,也就是字符串的地址。

字符串赋值?拷贝?
	char p[] = "abc";//创建一个字符数组
	char*q = new char[4];//动态申请内存
	q = p;//此时p和q都是“abc”,但是两者指向的内存是同一个内存
	cout <<q << endl;
	return 0;
输出结果:
abc
    char p[] = "abc";
	char*q = new char[4];
	q = p;
	cout <<q << endl;
	*(p + 1) = 'a';//修改p[1],此时q也会被修改
	cout << q << endl;
	return 0;
输出结果:
abc
aac

所以要想要实现字符串的拷贝是不能直接复制的,必须用解引用符实现逐个字符拷贝才行,这也是字符串拷贝函数的底层实现原理。

指针和结构体

在这里插入图片描述

指针和数组
char* getname()
{
	char temp[80];
	cin >> temp;
	//char*p = new char[strlen(temp) + 1];
	//strcpy(p, temp);
	return temp;
}
int main()
{
	char *p = getname();	
	cout << p;
	
}
输出结果:
乱码!!!!!
char* getname()
{
	char temp[80];
	cin >> temp;
	char*p = new char[strlen(temp) + 1];
	strcpy(p, temp);
	return p;
}
int main()
{
	char *p = getname();	
	cout << p;
	delete []p;
}
输出结果:
abc  ------结果正确

为啥会这样呢?因为temp数组是一个自动变量,当getname函数结束时,temp使用的内存会被自动释放,而如果返回一个地址的话,p指向的内存很快会得到重用,这也是为什么用new的原因

分配内存的三种方式

C++有三种分配内存的方式,分别是静态存储,自动存储和动态存储,C++11增加了线程存储(后续介绍)。
自动变量:是一个局部变量,作用域为包含它的代码块,存储在栈空间。
静态存储:生命周期贯穿于程序始终。
动态存储:存储在堆空间
内存泄漏:申请了内存,使用完毕后没有及时归还。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值