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