C++ - 复合类型

复合类型

数组

数组是一种书类型,能够存储多个同类型的值。每个值都存储在独立的数组元素中,计算机在内存中依次存储数组的各个元素;

数组的很多用途是基于这样的一个事实,可以单独访问数组元素,方法是使用下标来索引对元素进行编号,C++数组从0开始编号;

在这里插入图片描述

编译器不会检查使用的下标是否被使用

int _tmain(int argc, _TCHAR* argv[])
{
    
    

	using namespace std;
	int yams[3];    // creates array with three elements
	yams[0] = 7;    // assign value to first element
	yams[1] = 8;
	yams[2] = 6;

	int yamcosts[3] = {
    
     20, 30, 5 }; // create, initialize array

	cout << "Total yams = ";
	cout << yams[0] + yams[1] + yams[2] << endl;
	cout << "The package with " << yams[1] << " yams costs ";
	cout << yamcosts[1] << " cents per yam.\n";
	int total = yams[0] * yamcosts[0] + yams[1] * yamcosts[1];
	total = total + yams[2] * yamcosts[2];
	cout << "The total yam expense is " << total << " cents.\n";

	cout << "\nSize of yams array = " << sizeof yams;
	cout << " bytes.\n";
	cout << "Size of one element = " << sizeof yams[0];
	cout << " bytes.\n";
	
	return 0;
}

在这里插入图片描述
如果我们操作一个下标不存在的数字,编译器并不会替我们去检查这个下标的值是否存在,编译器是可以正常编译通过的,但是程序运行会崩溃;

字符串

字符串是存储在内存中连续字节中的一系列字符。存储在连续字节中的一系列字符意味着可以将字符串存储在char数组中,每个字符都位于自己的数组元素中;
字符串一定以\0结尾

	char dog[8] = {
    
     'b', 'e', 'a', 'u', 'x', ' ', 'I', 'I' };		//这种初始化方式编译器不会报错,但执行结果可能不是我们预期的结果
	char cat[8] = {
    
     'f', 'a', 't', 'e', 's', 's', 'a', '\0' };

	char bird[11] = "Mr,Cheeps";
	char fish[] = "Bubbles";

在这里插入图片描述

string类

C++98标准通过string类扩展了C++库,因此可以使用string类型的变量而不是使用字符数组来存储字符串;

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    
    
	using namespace std;
	char charr1[20];            // create an empty array
	char charr2[20] = "jaguar"; // create an initialized array
	string str1;                // create an empty string object
	string str2 = "panther";    // create an initialized string

	cout << "Enter a kind of feline: ";
	cin >> charr1;
	cout << "Enter another kind of feline: ";
	cin >> str1;                // use cin for input
	cout << "Here are some felines:\n";
	cout << charr1 << " " << charr2 << " "
		<< str1 << " " << str2 // use cout for output
		<< endl;
	cout << "The third letter in " << charr2 << " is "
		<< charr2[2] << endl;
	cout << "The third letter in " << str2 << " is "
		<< str2[2] << endl;    // use array notation
	return 0;
}

字符串初始化

char first_data[] = {
    
     "Le Chapon Dodu" };
char second_data[] = {
    
     "The Elgant Flate" };
string third_data = {
    
     "The Bread Bow" };

其他类型

除char以外,C++还有wchar_t;而C++11新增了char16_t和char32_t;

wchar_t title[] = L"Chinese Boy";
char16_tname[] = u"sYstemk1t";
char32_car[] = U"Humber Super";

结构

C++中结构是一种比数组更加灵活的数据结构,因为同一个结构可以存储多种类型的数据;

struct inflatable
{
    
    
	char cName[20];
	float fVolume;
	double dPrice;
};

int _tmain(int argc, _TCHAR* argv[])
{
    
    
	inflatable hat;
	inflatable woopie_cushion;
	struct inflatable gooes;			//在C++中可以省略struct关键字
	return 0;
}

使用.来访问结构体的成员

扫描二维码关注公众号,回复: 12422495 查看本文章

使用结构


struct inflatable
{
    
    
	char cName[20];
	float fVolume;
	double dPrice;
};

int _tmain(int argc, _TCHAR* argv[])
{
    
    
	inflatable guest = {
    
    
		"sYstemk1t",
		1.88,
		20.00
	};
	inflatable pal = {
    
    
		"pal",
		2.88,
		22.00
	};

	cout << guest.cName << " " << guest.dPrice << " " << guest.fVolume << endl;
	cout << pal.cName << " " << pal.dPrice << " " << pal.fVolume << endl;
	return 0;
}

C++11结构初始化

void test01()
{
    
    
	inflatable duck{
    
     "sYstemk1t", 0.12, 3.14 };
	cout << duck.cName << " " << duck.dPrice << " " << duck.fVolume << endl;
}

struct perks
{
    
    
	int nKey_number;
	char car[12];
}mr_glitz = 
{
    
    
	7,
	"sYstemk1t"
};

void test02()
{
    
    
	cout << mr_glitz.car << endl;
	cout << mr_glitz.nKey_number << endl;
}

结构中位字段

struct torgle_register
{
    
    
	unsigned int SN : 4;
	unsigned int : 4;
	bool goodIn : 1;
	bool goodTorgle : 1;
};

void test03()
{
    
    
	torgle_register tr = {
    
     14, true, false };
	if (tr.goodIn)
	{
    
    
		;
	}
}

共用体

共用体是一种数据格式,它能够存储不同的数据类型,但只能同时存储其中的一种类型;

共用体的用途之一,当数据项使用两种或多种格式时,可以节省空间;

struct widget
{
    
    
	char brand[20];
	int type;
	union id
	{
    
    
		long id_num;
		char id_char[20];
	}id_val;
};

void test02()
{
    
    
	widget w;
	w.type = 1;
	if (w.type == 1)
	{
    
    
		cin >> w.id_val.id_num;
	}
	else
	{
    
    
		cin >> w.id_val.id_char;
	}
	cout << w.id_val.id_num << endl;
	cout << w.id_val.id_char << endl;;
}

由于共用体没有名称,其成员将为位于相同地址处的变量。显然,每次只有一个成员是当前的成员;

枚举

C++的enum关键字提供了另一种创建常量的方式,这种方式可以替代const,它允许定义新类型,但必须严格限制;


enum spectrum
{
    
    
	red,orange,yellow,green,blue,violet,indigo,ultravlet
};

void test()
{
    
    
	spectrum band;
	band = blue;
	//band = 2000;		//错误赋值
}


指针和自由存储空间

指针也是一个变量,只不过其存储的是值的地址,而不是值本身;

int _tmain(int argc, _TCHAR* argv[])
{
    
    
	int donuts = 6;
	double cups = 4.5;

	cout << "dontus:" << &donuts << endl;

	cout << "cups:" << &cups << endl;
	return 0;
}

显示地址时,实现是以16禁止表示法,常用内存表示法;

指针用于存储值的地址中表示了我们存储的值,我们需要对指针进行解引用;

void test01()
{
    
    
	int updates = 6;
	int* p_update;
	p_update = &updates;
	cout << "updates = " << updates << endl;
	cout << "updates memory:" << &updates << endl;
	cout << "p_update = " << *p_update << endl;
	cout << "p_update = " << p_update << endl;
}

在这里插入图片描述

声明和初始化指针

指针的初始化,表示计算机需要跟踪指针指向的值的类型;

void test02()
{
    
    
	int higgens = 5;
	int* pt = &higgens;
	cout << "higgens = " << higgens << " " << "higgens memory = " << &higgens << endl;
	cout << "pt = " << *pt << " " << "pt memory = " << pt << endl;
}

指针的危险

在C++中创建指针的时候,计算机将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存;

指针和数字

指针虽然不是整形,但是它在内存中占用4字节;整形我们可以用于运算,但是指针用于没有意义,因为两个地址做运算没有任何意义;
在这里插入图片描述

void test03()
{
    
    
	int* p;
	//p = 0x12345678;		//错误赋值
	p = (int *)0x12345678;
	cout << *p << endl;		//这个输出没有任何意义,因为0x12345678这个地址也许没有被申请,访问空内存,自然也不会有输出
}

new分配内存

变量是在编译时分配的有名称的内存,而指针至少为可以通过名称直接访问的内存提供了一个别名。真正的指针强大之处在于,在运行阶段分配未命名的内存以存储值;


void test04()
{
    
    
	int* p = new int;			//new一个整形的内存并把地址赋值给变量p
	cout << p << endl;

}

new分配的内存对象处于内存的堆区

void test05()
{
    
    
	int higgens = 1001;
	int*p = new int;
	*p = 100;
	double* pd = new double;
	*pd = 3.1415926;
	cout << "higgens = " << higgens << "higgens memory = " << &higgens<< endl;
	cout << "p = " << *p << "p memory = " << p << endl;
	cout << "pd = " << pd << "pd memory = " << &pd << endl;
	cout << "psize = " << sizeof(p) << endl;
	cout << "pdsize = " << sizeof(pd) << endl;
	cout << "psize = " << sizeof(*p) << endl;
	cout << "pdsize = " << sizeof(*pd) << endl;

}

delete释放内存

当需要内存的时候,可以使用new来请求分配,但是当这块内存使用完毕后,我们往往需要释放这块内存,计算机内存并不是无穷无尽的,所以我们需要将内存归还给内存池;

void test06()
{
    
    
	int* ps = new int;
	delete ps;				//释放ps指向的内存,并不会删除指针变量ps本身,可以将ps重新指向一个分配的内存块;
	delete ps;				//重复释放

	int jugs = 5;
	int* pi = &jugs;
	delete pi;				//错误,只可以使用delete来释放new申请的内存

	

动态数组

我们在编译初期并不知道我们需要申请多大的一块内存,所以我们希望通过声明来创建数组,使得它在被编译的时候为它分配内存空间。不管程序是否使用,数组都存在,占用内存;
在编译时给数组分配内存被称为静态联编,意味着数组是在编译时加入到程序中去的,使用new时,在运行阶段时选择数组的长度,如果不需要,则不创建;

new创建动态数组

在C++中,创建动态数组很容易,只需将数组的元素类型和元素个数告诉new即可;必须在类型名后加方括号;

void test07()
{
    
    
	int* psome = new int[10];			//创建10个int元素的数组;
	delete[] psome;				//释放动态数组
}

  • 不要使用delete来释放不是new分配的内存
  • 不要使用delete释放同一个内存块两次
  • 如果使用new[]为数组分配内存,则使用delete[]来释放
  • 如果使用new[]为一个实体分配内存,则使用delete来释放
  • 对空指针应用delete是安全的

使用动态数组

void test08()
{
    
    
	double* p3 = new double[3];
	p3[0] = 0.2;
	p3[1] = 0.5;
	p3[2] = 0.8;
	cout << "p3[1] is " << p3[1] << endl;

	p3 += 1;				//加类型的步长
	cout << "p3[1] is " << p3[1] << endl;

	p3 -= 1;
	cout << "p3[1] is " << p3[1] << endl;

	delete[] p3;			//释放内存
}

指针算术

指针和数组基本等价的原因在于算术和C++内部处理数组的方式;

void test09()
{
    
    
	double wages[3] = {
    
     1000.0, 2000.0, 3000.0 };
	short stacks[3] = {
    
     3, 2, 1 };

	double* pw = wages;
	short* ps = &stacks[0];

	cout << "pw = " << pw << "," << *pw << endl;
	pw += 1;
	cout << "pw = " << pw << "," << *pw << endl;

	cout << "ps = " << ps << "," << *ps << endl;
	ps += 1;			//加法是指针的步长,指针的步长是当前类型的长度
	cout << "ps = " << ps << "," << *ps << endl;
}

在这里插入图片描述

动态结构

在运行时创建数组优于在编译时创建数组,对于结构也是如此。需要在程序运行时为结构分配空间,这也可以使用malloc或new来完成;


struct inflatable
{
    
    
	char cName[20];
	float fVolume;
	double dPrice;
};
void test10()
{
    
    
	inflatable* ps = new inflatable;		//将存储inflatable结构的一块内存的地址赋值给ps
	strcpy(ps->cName, "sYstemk1t");
	ps->dPrice = 3.1415926;

	(*ps).fVolume = 6.281234;

	cout << ps->cName << endl;
	cout << (*ps).fVolume << endl;
	cout << ps->dPrice << endl;
}

同样的,结构指针不可以使用(.)来访问了,我们需要使用特定的(->)来访问指针结构成员;但是我们同样也可以使用指针类型点的方式来读取结构内的值;

函数使用指针


char* getname(void);

void test11()
{
    
    
	char* name;
	name = getname();
	cout << name << "at" << (int *)name << endl;
	delete[] name;

	name = getname();
	cout << name << "at" << (int *)name << endl;
	delete[] name;
}

char* getname(void)
{
    
    
	char temp[_MAX_PATH];
	cout << "Enter last name:";
	cin >> temp;
	char* pn = new char[strlen(temp) + 1];
	strcpy(pn, temp);
	return pn;
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43791961/article/details/113099673