您的位置:首页 > 其它

(五十八)结构与指针

2015-12-03 17:24 218 查看
在使用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可能造成内存泄露
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: