在使用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可能造成内存泄露