(五十八)结构与指针

在使用new来创建动态结构时,表示创建的新结构中的某个变量,和普通结构中某个变量的形式不同。例如:


#include<iostream>
#include<string>
using namespace std;

struct ab	//定义一个结构ab
{
	string a;	//名字
	int b;	//重量或数量
	double c;	//单价
};

int main()
{
	ab *shuiguo = new ab;	//声明结构水果(shuiguo),使用结构ab形式,通过new的形式创建动态结构
	cout << "输入水果的名称:" << endl;
	getline(cin, shuiguo->a);	//因为是string类型,所以需要使用getline(cin,结构中的变量名)这种形式,对于非动态结构,shuiguo->a就类似shuiguo.a
	cout << "输入水果的重量(斤):" << endl;
	cin >> (*shuiguo).b;	//(*shuiguo).b和shuiguo->b是等价的
	cout << "输入水果的单价(元/斤):" << endl;
	cin >> shuiguo->c;	//指针名->结构变量名 和 结构名.结构变量名 是等价的
	cout << "输入结束。\n经过计算:" << shuiguo->a << "的重量为" << shuiguo->b << "斤,单价为" << shuiguo->c << "元/斤。" << endl;	
	//使用箭头运算符来表示动态结构中的某个变量
	cout << (*shuiguo).a << "的总价值为" << shuiguo->b*(*shuiguo).c << "元" << endl;
	//带箭头运算符表示的结构中某个变量,可以直接用于表达式
	cout << shuiguo << endl;
    delete shuiguo;
	cout << endl;
	ab bi;	//声明结构笔(bi),使用ab结构的形式
	bi.a = "铅笔";	//结构bi的名称为 铅笔
	bi.b = 15;	//数量为15
	bi.c = 0.5;	//单价为0.5元/根
	cout << bi.a << "的单价为" << bi.c << "元/根,我们要买" << bi.b << "根" << bi.a << "。\n";
	cout << "经过计算,需要花费" << bi.b*bi.c << "元。" << endl;


	system("pause");
	return 0;

输出:


输入水果的名称:
苹果
输入水果的重量(斤):
25
输入水果的单价(元/斤):
3.33
输入结束。
经过计算:苹果的重量为25斤,单价为3.33元/斤。
苹果的总价值为83.25元
005B09F8

铅笔的单价为0.5元/根,我们要买15根铅笔。
经过计算,需要花费7.5元。
请按任意键继续. . .

①在使用定义的ab结构时,创建一个结构。

假如使用的是普通结构。即:“定义结构名 结构名”如ab bi; 那么表达bi这个结构中某个变量的办法是bi.变量名。

 

假如使用new来创建动态结构,创建方法为“定义结构名 *指针=new 定义结构名”即ab*shuiguo = new ab

在表达结构中的变量时,有两种表达形式:(*指针名).结构变量名 或者 指针名->结构变量名 。即(*shuiguo).a或者shuiguo->a 。前者是类似普通结构,指针加解除运算符(*)相当于 结构名 来理解。对比而言,二者形式相近:

(*bi).a  和  shuiguo.a

 

②无论是(*shuiguo).a或者是shuiguo->a,都可以直接运用在表达式之中,和我们使用普通结构没什么区别。

 

③由于shuiguo是指针,所以cout<<shuiguo<<endl;输出的是指针指向的内存地址。

 

④因为是使用new创建动态结构,因此对应的可以使用delete来删除动态结构。具体格式为:delete 指针名。如:delete shuiguo;

 

 

 

使用new创建字符串来节约内存:

之前使用new来创建动态结构,其实new和delete也可以在不同的函数中使用,例如一个函数分配内存,一个函数释放内存。特别是在涉及循环的时候,可以节约不少内存。如代码:

#include<iostream>

char *getname(void);	//这是一个函数原型,在开始进行声明,之后才能调用。
//char*类型表示返回的是字符串,void表示无需输入
using namespace std;

int main()
{
	char*a;
	a = getname();	//给指针a赋值,值为函数getname()的返回值。注意,指针a和指针c指向的内存地址是相同的
	cout << "在主函数里,把指针c的地址赋给指针a,指针a的值为" << a << endl;	//输出指针a所指向地址的值
	cout << "指针a的地址为" << (int*)a << endl;	//输出指针a所指向的地址
	delete []a;	//删除指针a
	cout << endl;

	a = getname();	//给指针a赋值,值为函数getname()的返回值
	cout << "在主函数里,把指针c的地址赋给指针a,指针a的值为" << a << endl;	//输出指针a所指向地址的值
	cout << "指针a的地址为" << (int*)a << endl;	//输出指针a所指向的地址
	delete[]a;	//删除指针a
	system("pause");
	return 0;
}


char*getname()
{
	char*b = new char[20];	//为指针b创建新地址
	cout << "随便输点什么,别超过20个字符" << endl;	
	cin.get(b, 20).get();	//将输入的内容赋值给指针b所指向地址里,并用.get()舍弃换行符
	cout << "你输入的是: " << b << endl;	//输出指针b所指向地址的值
	cout << "你输入的位置所在的内存地址为:" << (int*)b << endl;	//输出指针b所指向地址
	char*c = new char[strlen(b) + 1];	//初始化指针c,并位置new一个新的内存地址
	strcpy_s(c, strlen(b) + 1, b);	//将指针b的值赋值到指针c指向地址的
	cout << "将你输入的字符串复制到指针c的位置。" << endl;
	cout << "指针c的地址为:" << (int*)c << endl;	//显示指针c所指向的地址
	cout << "指针c所指向地址的值为" << c << endl;	//显示指针c所指向地址的值

	return c;
}

输出:


随便输点什么,别超过20个字符
abc
你输入的是: abc
你输入的位置所在的内存地址为:004309F8
将你输入的字符串复制到指针c的位置。
指针c的地址为:00430658
指针c所指向地址的值为abc
在主函数里,把指针c的地址赋给指针a,指针a的值为abc
指针a的地址为00430658

随便输点什么,别超过20个字符
def
你输入的是: def
你输入的位置所在的内存地址为:00430658
将你输入的字符串复制到指针c的位置。
指针c的地址为:00430698
指针c所指向地址的值为def
在主函数里,把指针c的地址赋给指针a,指针a的值为def
指针a的地址为00430698
请按任意键继续. . .

char*c = new char[strlen(b) + 1];这行代码,可能为指针c两次new到相同的内存地址,也可能new到不同的内存地址。

 

②因为指针a指向的地址为指针c所指向的地址,所以指针a指向的地址和指针c指向的地址是相同的;

而指针c相对于指针b来说,是new了一个新地址,因此和指针b的地址是不同的;

指针b每次都new了一个新地址,所以也可能是不同地址(但由于之前delete指针a),因此也可能是不同的;

 

③根据实际测试,delete []a;和 delete a; 都能顺利运行,但按之前来说,删除字符串指针应该是delete []a; 才对。

 

④在删除指针的情况下,下一次new,是有可能new到相同的内存地址的。

 

⑤在函数getname()之中,执行完函数之后,指针b和指针c因为是自动存储,因此之后无法再次访问指针b和c,但因为没有被delete,所以其占用的内存地址还在。但是指针c和指针a指向的内存地址相同,delete了指针a,实际上也释放了指针c所指向的内存地址,但是没有释放指针b所指向的内存地址。参照(五十九自动存储),因此,指针b可能造成内存泄露


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值