第四天(复合类型 · 二)

来源:互联网 发布:linux查看ssh端口 编辑:程序博客网 时间:2024/06/05 10:35

    昨天,本来想看一下视频调节一下因为整个下午看C++而形成的疲惫之心,不过一看就上瘾,所以上传玩笔记后就没怎么看书了,有点后悔。恩,今天的打算是看一下网易公开课,看有没有C++或其它的,这个应该不会上瘾吧,之后在看一下其它书。


2011-10-02(Compound Type II)
1、观察下面两段代码:
                                       int a = 5;
                                       int *p=&a;

                                       int a = 5;
                                       int *p ;
                                       *p = &a;
后者报错。两者的形式就像int a = 5;int b;b = a;和int a = 5;int b = a;一样,为什么会报错了。其中的原因是*操作符扮演的角色不一样,前者只是表示p是int型指针,其中的*仅是一个标志符号,其实质是和int、float一样,让编译器知道这是一个指针,需要分配什么样的空间给它。如果把空格位置移一下(是允许的)或许会明显一点:int* p = &a;将int*视作一个整体,表明后面的p是int型指针;

后者,*是作为一个操作符的,称为解除引用(dereferencing)操作符,可以得到这个地址处储存的值,即*p是int型的,&a却是一个int型地址。
2、用new分配地址。回想,一个变量有两个属性:一个是变量本身的的名字以及指向它的指针的名字。那么使用变量有三种方式:单独使用其中某一个或者两者同时使用。
方式一:先声明一个变量,而后声明一个相应的指针,用该指针指向它,同时使用它的两种属性。这是C语言的做法,或言这是面向过程编程的做法;
方式二:先找一块内存,而后声明一个相应的指针指向它,注意这里仅是找,并没有为找到的内存起名,所以这里仅使用指针来对变量进行操作。这是C++的做法,或言只是面向对象编程的做法;
方式三:仅使用变量本身,这是没学指针的做法~~。
下面语句,对应于方式二,也是C++的指针使用方式:
                                 typeName *p = new typeName;
new是一个关键词,用于寻找和typeName相匹配的内存块,并返回这个内存块的地址,由同为typeName型的指针接收。这个内存块没有名字,可广义地称为数据对象(data object)。
3、用delete释放地址。一般的操作如下:
                                       int* p = new int;
                                       //... ...
                                       delete p;
①释放的作用效果。释放的意思是将已经被p指向的地址重新变成自由内存,不在与之前p有任何联系。这个p依然在这里,依然是int型的指针,即delete操作后,所剩下的东西是int* p;
②不能释放两次内存。delete的本质是作用于且仅作用于new操作所找到的空间,p只是这个空间的名字,当delete释放一次后,剩下的只是一个int型的变量,如果这时再次delete p,delete作用的对象已经不同了,是不允许的。下面的语句也是不允许的:
                                       int* p = new int;
                                       int* q = p;
                                       delete p; delete q;
这里,p、q是new所找到空间的两个名字,同样犯了释放两次内存的错误;
③不能释放声明变量所获得的内存块。如上所述,用&获得的内存不同于new获得的内存。
4、动态数组。
①创建。typeName* p = new typeName[numElements];p指向的是数组的第一元素,即p[0];
②释放。delete [] p;注意这个p必须是一个数组的头元素;
sizeof(arrayName) = 数组长度;sizeof(pointerName) = 地址长度。
C风格创建数组:typeName arrayName[numElements],采用的是静态联编(static binding),即数组长度在编译时设置;C++风格创建,采用的是动态联编(dynamic binding),即在运行时为数组分配空间。
5、字符串的输出和输入。
①输出。

#include <iostream>using namespace std;int main(){    char a[] = "abc";    char* p = "cde";    char* q;    q = a;    q++;    cout << a << "teg" << endl; //Print: abccteg    cout << p << endl; //Print: cde    cout << q << endl; //Print: bc    return 0;}
上面的程序中,a、p、q都是地址,而且是char *。于是可以武断地说,如果cout接收的是char型地址,它会从该字符开始打印,直到遇到空白字符为止。后面的常量"teg"其实传递给cout的只是字符't'的地址。事实上,C++中,对于数组中的字符串、引号括起来的字符串常量和指针所描述的字符串,打印的时候都是传递它们的地址。一遇到char地址,cout就打印其内容,这是cout对字符串的偏爱,其他类型,如int *、double *都是打印地址值的。如此,如果需要打印char *地址则需将其强制转换成其他类型,如:
                                  cout << (int *)a << endl;
②输入。输入的话,就对地址及地址所指向的东西有严格要求。C中接收输入流的东西有两样:字符数组、char型指针(如上面的p、q)。如果char型指针未初始化(如q),则可能会带来严重后果。而已初始化的(如p),系统则将其视作一个常量,一个不可改变的常量,所以想通过cin或者get()等函数改变它是不可能的了。如此,接收者只能是字符数组。当然C++中提供了std::string来接收。
6、用new创建动态结构。如下形式:
                                  structure *p = new structure
衍生出的问题是如何访问结构体成员。因为这里结构体并没有命名,不能使用"."。解决的办法是使用操作符“->”,由连字符和大于号组成:p->structMember等效于以前的structName.structMember。也可以配合解除引用号("*")来访问:(*p).structMember,这里的括号必须有。


今天的笔记有点短,加个课后编程练习题:

/*Devise a structure named Pizze to hold 3 kinds of information. Using the keyword new to allocate memory.*///P110 Exercise 8#include <iostream>#include <string>using namespace std;struct Pizza{string name;double diameter;double weigth;};int main(){Pizza *p = new Pizza;cout << "What is the diameter of this pizza? Enter: ";(cin >> p->diameter).get();cout << "What is the name of the pizza company? Enter: ";getline(cin,p->name);cout << "How much does the pizza weigh? Enter: ";cin >> p->weigth;cout << "\nHere are the information: \n";cout << "Company name: " << p->name << endl;cout << "Diamter: " << p->diameter << endl;cout << "Weigth: " << p->weigth << endl;return 0;}