C++学习笔记(一)


一、前言

2018年一月,闭关九日,进度比预期慢了许多,但这几日阅读《C++ primer plus》以及诸位前辈的技术博客也学到了许多新知识,今晚将这几日收获做了简单总结,是一些十分浅显的C++入门知识,其中省略了一些c语言的基础知识。


二、预备知识


1、c++的三种模式

  1OPP面向对象编程,是管理大型项目的工具。

  2】泛型编程(c++模板),用于执行常见任务。

  3】过程化编程(c语言)


2、类是一种规范,描述新型数据结构,同时规范有哪些数据及如何对其操作。对象是根据这种规范的特定数据结构。

   即类指某方面类别,对象指具体情况。如 类:头衔,对象:副主席。


3、opp的设计方法首先设计类,是从低级组织(类)到高级组织(程序)的,叫做自下而上的编程,好处在于创建可重用的代码。


4、int main()是函数头,作为与操作系统的接口。


5、位于函数名前的类型名叫做返回类型,函数名后的括号叫做形参列表,空括号意味着不接受任何参数。参数(argument)指一个函数传递给另一个函数的信息。


6、int mainvoid)在c++中指不接受任何参数,与空着等效。C语言中,空着表示沉默。


7、常规编程必须有main函数,有极少数例外情况,非独立程序(如DLL模块),专用环境的程序(如机器人)。


8、头文件,iostream 中的io指输入输出,使用cin cout必须使用iostreamANSI/ISO委员会同意不使用扩展名.h,所以应使用名称空间编译指令,使他对程序可用。名称空间支持是C++特性。名称空间:namespace。一般用using namespace std; 就是指用名称空间中的std

这叫做using编译指令。


9、类、函数、变量为C++编译器标准组件,他们都被放置于名称空间(std)中,这实际上是一种偷懒行为,且违背了名称空间的初衷。若不偷懒,应使用类似于using std::cout这样。


10、cout cin的最大区别是:cout后面跟的是<<,表示是输出内容。

比如cout<<”孙dua真高啊”<<endl;  代表输出文字 孙dua真高啊,并且换行(endl;)。

cin 表示的是输入,后面跟的是>>, 比如:

int height;
cout<<”输入孙刚新的身高<<endl;
cin >> height; 
cout <<”孙刚新”<<height<<”了”<< endl;

代表先显示让你输入孙刚新的身高,然后height 被你输入数字赋值。

这里面的>><<表示信息流的方向。


11C++中可以连续使用赋值。

Licaodan = sungangxin = 2.88

顺序为从右到左。


12、coutostream的类对象,cinistream的类对象,在iostream中定义,类描述指定了可对类对象执行的所有操作。


13、C++的两种发送消息方式。(1)使用类方法【即函数调用】(2)重新定义运算符。


14、函数是用于创建C++的模块,参数是发送给函数的信息,返回值是从函数中返回的值。C++允许在任何地方声明新变量,还允许在创建时对他赋值。函数不允许嵌套,所有函数平等。


15、应在首次使用前提供原型,把原型放在main函数前面。(库函数),自己定义的放在main后面。


三、处理数据


1、变量名有三点注意。

1)只能用字母、数字、下划线(2)第一个不可为数字(3)区分大小写。

 在这里也要提一句,相信看这一份笔记的同学和我现在一样都是初学者,在编程中对变量的命名最好有自己的规范,整洁优美,我选用的是驼峰命名法。


2、以两个下划线或下划线和大写字母开头的名称被保留给编译器使用。以一个下划线开头的名称保留给编译器,用作全局标识符。(这两处编译器,在c++ primer plus中被翻译为实现,指编译器及其使用资源,我在这里直接称作编译器。)


3、climits定义了符号常量。


4、sizeof对类型名使用时应放入括号内,如 sizeof (int),对变量名使用时,括号可有可无。


5、若使用表达式来初始化变量,条件是当程序执行到该声明时,表达式中所有的值都是已知的。


6、C++中有一种c没有的初始化语法,int nb(111);


7、C++11中有一种初始方式用于数组和结构,但在c++98中,也可用于单值变量。

 Int rheas = {24};(1)等号可以省略(2)大括号中可不包含任何东西,初始化为零。(3)可防范类型转换错误。

注意,一些oj和比赛不支持c++11 (比如蓝桥杯)。


8、基本类型有两组,整型和浮点类型。

整型从小到大排列:

bool(bool只有1和0,即true or false)、char、signed char、unsigned char、short、unsigned short、int、unsigned int、long、unsigned long

以及c++11新增的long long和unsigned long long。外加一种wchar_t

为节省内存(只有大型整型数组时),使用short。如只需一个字节,使用char。

C++11还有新增的类型char16_t和char32_t, 这两个的宽度足以用于存储16位和32位的字符编码。


在长度上,short至少为16位,int大于等于short的长度,long最少32位,long大于等于int的长度。

字符可以通过其数值编码显示,而I/O系统决定编码到底显示为字符还是数字。(比如cout和cin)

而浮点类型三种,按长度排序float,double,long double。即float不比double长度长,而double不比float长。通常来说float使用32位内存(6位有效数字),double占用64位内存,而long double占用更多内存。

 

浮点数的位指有效位,即数字中有意义的位,举例子很好弄懂了。12345有5个有效位,12300的却只有2个有效位,12045有5个有效位,12040有4个有效位。

也就是说,数字中从第一个非0数字开始算起,到最后一个非0数字为止,中间的数字都属于有效数位。至于中间有没有小数点,并不重要。例如12345和1.2345的有效数位是一样的。

 

而浮点数的表示方法有两种:

<1>带小数点,并且至少带小数点后一个0。

例如:3.1415  ;  165.1  ;  0.331  ;  6.0等

<2>不带小数点,带E,具体方式是:aEb——(E或者e表示10,b表示10的b次方,aEb表示数字a乘以10的b次方)

例如:1.2E5表示1.2*100000;3.11E-4表示3.11乘以10的-4次方(即0.0001);-10e4表示-10乘以10000等。

b理解为小数点往右(b为正时)或者往左(b为负时)移动b位。

 


9、进制一般使用三种,但无论使用哪种,在计算机眼里都是二进制(红粉骷髅hhhh),不需要白费力气非要翻译成十进制。

1)十进制:基数为10。 第一位是1~9。例如11他就是十进制的11;

2)八进制:基数为8(逢8进一)。第一位是0,例如033,是十进制的27;

3)十六进制:基数是16(逢16进一)。第一位是0X或者0x,例如0X11,是十进制的17(1*16+1)。

这三种的控制符分别为 dec、hex、oct。

cout输出时,默认使用十进制。十六进制一般用来表示内存地址,而内存地址没有符号,因此unsighed int 比long更适合用来表示16位地址。

 

见以下范例。

#include <iostream>
using namespace std;
 
int main()
{
	int a = 123;
	int b = 0123;	//b为八进制的0123
	int c = 0x123;	//c为十六进制的0x123
	cout << "a= " << a << endl;	//显示a的结果
	cout << "b= " << b << endl;	//显示b的结果(注:转为十进制显示)
	cout << "c= " << c << endl;	//显示c的结果(注:转为十进制显示)
	cout << endl;
 
	cout << hex;	//告诉程序你应该以十六进制(hex)方式显示整数
	cout << "a= " << a << " ←这里以十六进制的方式显示a" << endl;	//显示a的结果(注:转为十六进制显示)
	cout << oct;	//告诉程序你应该以八进制(oct)的方式显示整数
	cout << "a= " << a << " ←这里以八进制的方式显示a" << endl;	//显示c的结果(注:转为十进制显示)
	cout << dec;	//告诉程序你应该以十进制(dec)的方式显示整数
	cout << "a= " << a << " ←这里以十进制的方式显示a" << endl;	//显示a的结果
 
	system("pause");
	return 0;
}

 

输出结果为:
a= 123
b= 83
c= 291
 
a= 7b ←这里以十六进制的方式显示a
a= 173 ←这里以八进制的方式显示a
a= 123 ←这里以十进制的方式显示a
请按任意键继续. . .

(1)八进制那里的显示,前面没有0。但是输入的时候要加0,不然程序以为你输入的是十进制。

(2)cout<<hex; 并不会显示任何东西,只是单纯的告诉编译器,以什么方式显示数字。(3)(3)标识符hex存在于命名空间std中,因此,变量名不能用hex,除非你不用using namespace std; 这行命令。另外,也只有用了这行命令,你才能简写hex,dec,oct。否则你就要用std::hex、std::dec、std::oct 等。


10、比如有一个short a; 我们有时候会给前面加上一个unsigned ,就变成了unsigned short a;

这个时候呢,因为short是16位,16位能表示出65536种数字。如果是short a;他的范围就是-32768 ~ +32767。加上signed也是一样的,如果加上unsigned呢,他的范围就变成了0 ~ 65535 了。

ps:unsigned 本身是 unsigned int 的缩写。

例如short a;  这里a的范围是-32768 ~ +32767

unsigned b; 这里b的范围是0 ~ +65535



short a(以下是a的取值)

a-1

a+1

0

-1

1

-32768

32767

-32767

32767

32766

-32768

a的取值范围

-32768 ~ +32767

 

unsigned b(以下是b的取值)

b-1

b+1

0

65535

1

1

0

2

65535

65534

0

b的取值范围

0 ~ 65535

12、类定义了如何表示和控制数据。成员函数归类所有,描述了操纵类数据的方法。例如类ostream里面有一个put()成员函数,用于输出字符。只能通过类的特定对象(例如这里的cout对象)来使用成员函数。
要通过对象(如cout)来说用成员函数,必须用句点将对象名和函数名称(put())连接起来,句点被称为成员运算符11、函数cout.put()是一个重要的C++ OOP(面向对象函数)概念——成员函数——的第一个例子。

cout.put ()通过类对象cout使用函数put,可以用来替代<<运算符。

13、用cout.put();  如果里面是变量,则显示变量的ASCII值所代表的字符,如果是整数,则显示ASCII值为该整数所代表的字符。里面先计算整数,再将整数转为字符输出。

cout.put('');  如果单引号里面是数字,则显示最后一位数字(小数也显示最后一位),如果单引号里面是字母,则显示字母。因为'a'是一个文本,所以直接显示这个文本,而不是转成ASCII值再输出字符。

14、转义序列。

换行符		 \n
水平制表符		 \t
垂直制表符			\v
退格键			\b
回车键		 \r
振铃(就是会bi~一声)		\a
反斜杠			\\


15、将转义字符作为字符常量的时候,用单引号,用在字符串中的时候,用双引号,字符串会在字符的最后加上空字符\0。


16、浮点运算的速度通常比整数慢,且精确度会降低。


17、应在声明中对const初始化。


18、强制转换有两种格式。

1) (long)thorn 这种来自C语言
2)long (thorn)这种是纯C++


19、C++引进了四种强制类型转换运算符,static_cast<>可用于值转换。如static_cast<long>(thorn)


20、类型转换,已经知道,int,double,short,char,long,float等多个类型,其中有整型,也有浮点类型。然而,在实际应用中,经常会涉及到类型转换问题。

例如
double a=13.33333333;
float b=a;

这个时候,实际上就是把double a的值赋值给float b,而又因为变量a和变量b的精度不同,所以在赋值的时候,C++需要将其类型进行转换。

又比如,两个类型为short的变量相加的结果,可能和2个long相加的结果不同(因为可能存在溢出,例如unsigned short的最大值为65535,如果2个short整型的65535相加,且将结果赋值给short类型的变量,新变量的数值必定不是65535*2)。


21、在以下三种情况,C++自动执行类型的转换(即无需我们进行转换)

①将一种算数类型的值赋给另外一种算数类型的变量时,C++自动进行转换。例如将int a=54321赋值给short b时,b的值则不为54321。但是如果将short b=1234赋值给int a时,a的值依然为1234。

即表示范围更大的类型(如int)赋值给表示范围更小的类型(如short)时,数值可能发生变化。超出部分通常只复制靠右边的部分。

表示范围更小的类型(如char)赋值给表示范围更大的类型(如short)时,数值不会发生变化,只是会占用更多的字节。

浮点类型转换成整型(如double转换为int),则自动丢失小数部分。

其他类型赋值给boo时,非0值被转换为true(1),0值为false(0)。


22、c++11中也新增了auto工具,会根据初始量的类型推断变量的类型。

auto a=1; 变量a类型为int

auto b=2.0; 变量b类型为double

auto c=3.1L; 变量c类型为long double——因为后缀加L表示是long double类型

auto d=4.333F; 变量d类型为float——因为后缀加F(f)表示是float类型

注意:auto a=0; 的时候,变量a的类型为int

按照说明,auto在处理简单变量的时候,使用的意义并不大,处理复杂类型,如标准模块库(STL)中的类型时,自动类型推断的优势才能显现出来


四、复合类型


1、数组(aaray)是一种数据格式,能够存储多个同类型的值。创建数组的声明应指出以下三点:

①存储在每个元素中的值的类型;②数组名;③数组中的元素数。

typeName arrayName【arraySize】


2、在初始化的时候,可以不用给所有数组中的值进行赋值,没有赋值的数组中的数,被认为是0。


3、确保程序只使用有效的下标值。


4、不能将一个数组中所有数直接复制给另外一个数组中的数;


5、一般不要让编译器计算数组中元素的个数,因为可能你自己在输入的时候漏掉一个或者几个数,这就麻烦了。但是这种方法,对于将字符数组初始化为一个字符串来说比较安全。


6、可以用sizeof来确认你数组中的元素数是否如你计划中的数量。比如int变量,一个是4字节,如果你数组中有5个数,那么sizeof数组应该为20个字节。

 Int numElements = sizeof things / sizeof (int);


7、C++11可以省略等号,可以不在大括号内包含任何使用东西使所有元素为零。


8、STL提供了数字替代品-----模板类vector


9、字符串是存储在内存的连续字节中的一系列字符。因为是内存中的连续字节中的一系列字符,意味着可以将字符串存储在char数组中。(因为字符是被存储为char类型的,又因为是连续的,可以认为是若干char类型的字符所组成的数组)。


10、字符串需要以空字符结尾,写作\0,其ASCII码为0,用于标记字符串的结尾。如果没有以空字符结尾的话,是不行的。——因为可能会显示更多的(不在字符串内容中)的字符。


11、字符串需要用char的数组,但是 不可以将字符数组当做字符串处理。


12、C++处理字符串有两种方式。

(1)来自c语言的c-风格字符串 (2)基于string类库的方法。(对于string,可以直接使用“ ”。


13、区分字符常量‘ ’和字符串常量“ ”,后者包括空字符\0,且指内存地址。


14、在数组中使用字符串方法有两种,(1)将数组初始化为字符串常量 (2)用cin输入。


15、头文件<string>中包含,strlen()确定长度,strlen只计算可见的,不包括空字符,数组长度需要为strlen+1。sizeof确定长度时包括空字符。


16、由于cin的机理,在读取用户输入的时候,对空格,tab,或者换行符没有响应,读取到空格,即以上三个情况后,自动停止读取。需要使用cin的较高级特性,或者采用getline()或者get()来读取一行。

getline()将读取到换行符位置,通过确认回车输入的换行符来确定输入的结尾,并将换行符丢弃(即不会读取换行符),将其换成空字符。而get()读取到换行符为止,并储存换行符。


17、调用getline()来读取一行,需要使用cin.getline(数组名,读取字符数),注意这里的读取字符数需要+1来包括空位符。


18、使用cin.getline()的确可以读取一整行,并且显示输出结果的时候,不会帮我们换行。

cin.get()函数与cin.getline()函数的区别也在这里体现。


19、假如我们输入内容为:abc(回车),使用cin.getline()的时候会读取abc,然后把(回车)丢掉,这样当我们下次输入def(回车)的时候,将读取def,然后再丢掉(回车)。

假如我们使用cin.get(),当输入abc(回车)的时候,先读取abc,但是并没有把(回车)丢掉,下一次输入cin.get()的时候,会首先读取回车,然后因为发现回车了,认为是最后一个字符,所以停止读取后面的内容,比如说def————准确说,这里的cin.get()是带参数的cin.get()会这样。

假如在两个带参数的cin.get()之间,加入一个不带参数的cin.get(),这个不带参数的cin.get()便可以处理掉那个未被读取的换行符。

举例

cout << "请输入你的身高:";
	cin.get(height, 20);
	cin.get();	//无参数的用于读取换行符
	cout << "请输入你喜欢的女生名字:";
    cin.get(girl, 20);

也可以写为:

	cout << "请输入你的身高:";
	cin.get(height, 20).get();	//在第一个cin.get()后面,加上.get()用于读取换行符
	cout << "请输入你喜欢的女生的名字:";
    cin.get(girl, 20); 

两个效果是一样的。和上面cin.getline()效果也相同。

注意,也可以这样输入:

cin.getline(height, 20).getline(girl,20 );	//连续读取两行输入的文字,并且分别储存于两个字符串之中

不过我觉得,这些知识了解就好,这么写不美观也不便于理解,没什么太大意义,用来应试考试的填空题倒是可以hh


20、假如用户输入的字符串超出字符串预设的长度(即比分配的长),那么多出来的部分将被下一个字符串所读取(在使用cin.get()的情况下),或者被舍弃,但下一个字符串用户需要输入的时候无法输入(在使用cin.getline()的情况下)。


21、string类可以将字符串视为输入到一个简单变量中,像使用一个变量那样使用他(即对象),而不是像字符数组来储存字符串。

前提是:使用头文件#include<string>,另外,string类位于名称空间std中,因此需要使用using namespace std;或者std::string 或者using std::string。

在其他方面,又类似字符串那样使用。例如,在声明并初始化的时候,需要给字符串加上双引号或者单引号,像 string abc="aaa"; 这样。


22、想要读取输入中的空格,就使用函数getline(cin,string变量名)。


23、string类的赋值:

我们知道,当有两个数组aaa,bbb时,其中aaa已经被初始化,但是bbb不能通过赋值的方式,将aaa中的字符串赋给数组bbb,如bbb=aaa;这种方式是错误的。

但是当有两个string类型的变量ccc和ddd时,假如ccc={"abbb"};已被初始化,是可以通过赋值的方式,将ccc的字符串赋给ddd,如ddd=ccc;cout<<ddd;的输出结果是abbb。


24、string类的相加,就是将两个string类型的变量进行合并,有两种方式。(1) str3=str1+str2; (2)str1 += str2

第一种方式是相加的两个变量没有变化,第三个变量为相加两个变量合起来之后的字符串。第二种方式是被变的string变量没有变量,目标string变量变化为两个变量合并起来之后的字符串。


25、sizeof无法识别出string类变量的所占空间,因为他是动态分配的。用 变量名.size()。例如 cout<<hh.size()<<endl; 此方法不计空白符。


26、至于c-风格,用strlen(hh)显示字符数,如果用sizeof(hh)则就包括空白符。


27、如果不是string类,而是C-风格的字符串。

可以使用strcat(目标字符串A,字符串B)来将字符串B的内容复制到字符串A的后面;

另外是strcpy(目标字符串A,字符串B)可以将字符串B全部复制到(即理解为赋值)到目标字符串A之中。

这就涉及到库函数的使用,在这里不展开叙述,我在打这篇笔记的时候看了很久qsort的使用,后来发现我用C++直接sort就好,所以各位这里可以只做了解,毕竟使用c++是为了提供效率,使用string类就好啦。


28、我们知道,cin是istream类的一个函数。cin.getline()的前缀是cin,通过英文句号和getline()相连。

因此,在这里,getline()是istream的一个类方法。cin.getline()是面对C-风格的字符串使用的。

而面对string风格的字符串时,我们使用的是getline(cin,变量名)因为没有使用句点的表示法,所以在这里,getline()便不是一个类方法。

他将cin作为参数,指出去哪查找输入,也没有指出字符串长度——因为string类可以自动调整长度。


29、其他类型的字符串字面值

之前在声明字符串的时候,C-风格是char 变量名[长度+1]={字符串}; 而string类风格是string 变量名={字符串};

除此之外,还有其他类型,

1)如wchar_t;
声明方法(字符串带L前缀):如wchar_t=L"abc";
(2)C++11后新增的char16_t和char32_t;
声明方法(16的前面带小写u,32的前面带大写U)。如:
char16_t=u"aabb";
char32_t=U"aaabbb";
(3) 原始(raw)字符串,在原始字符串里面,输入的字符都表示自己,例如\n在普通字符串里是换行,在原始字符串里显示\n。方法是前面加R,字符串的前后使用引号括号和括号引号。假如要在让原始字符串里面显示"(和)",方法是,把字符串前后原本的"(和)"改成"+*(和)+*"。


30、结构是OPP的基础,结构可以同时储存int、float、double、char类型。


31、结构的声明格式为:

struct 结构名
{
类型名1 变量名1;
类型名2 变量名2;
……	……
}

一般使用外部结构声明,即在int main(){}外进行声明。

在创建结构数组的时候,一般在int main()的内部进行。

使用同一种结构的两个结构,可以直接通过“=”等号进行赋值。


32、在创建结构的时候同时赋值。方法是:

 
struct 结构名
{
类型名 变量名;
…… ……;
}使用该结构的某个结构变量名=
{
1;
……;
};

如代码:

#include<string>

struct abc{std::string name;std::string price;}apple = { "苹果","5元一斤" };//在结构定义后直接声明变量//非直接声明的形式如下://abc apple={ "苹果","5元一斤" };//相当于节省了一个结构定义名 int main(){using namespace std;abc banana = apple;cout << "水果名字为:" << apple.name << "。价格为:" << apple.price << endl;banana.name = "香蕉";banana.price = "3元一斤";cout << "水果名字为:" << banana.name << "。价格为:" << banana.price << endl;system("pause");return0;}

但这种办法不清晰,将结构定义和声明结构(初始化结构)的时候分开使用,可以让代码阅读起来更清晰和容易理解。


33、若有两个变量,可以创建一个数组,数组的每个元素都是同一个结构定义。

 

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

struct abc
 
{
string name;
string price;
};
 
int main()
 
{
abc shuiguo[2]=  //创建数组shuiguo,数组元素数为2(即数组中有两个结构作为元素),第一个元素为shuiguo[0],第二个元素为shuiguo[1]
{
{"苹果","5元一斤"},  //给数组中第一个元素——shuiguo[0]结构进行初始化,注意,结尾是逗号。赋值方法等同给普通结构初始化。
{"香蕉", "3元一斤"}  //给数组中第二个元素——shuiguo[1]结构进行初始化,注意。结尾无符号。
};
 
cout << "第一个水果名称为:" << shuiguo[0].name << "。价格为:"<<shuiguo[0].price << endl;//显示数组中第一个元素相应的值
 
cout << "第二个水果名称为:" << shuiguo[1].name << "。价格为:"<<shuiguo[1].price << endl;//显示数组中第二个元素相应的值
 
//注意用数组的时候,原本是 结构名.变量名,现在为 数组名[N-1].变量名 ,N为第N个元素。数组名 其实就是变相的 结构名,
 
//只不过结构名需要自己在初始化的时候进行声明,而 数组名 是共享一个名字,只不过括号里的数字不同,实质上还是一样的。
 
system("pause");
 
return0;
 
}
 
 
 
输出:
 
第一个水果名称为:苹果。价格为:5元一斤
 
第二个水果名称为:香蕉。价格为:3元一斤
 
 


34、

定义结构时,使用指定的位数:

在定义结构的时候,可以指定每个变量使用特定长度位数,比如4位,8位等。格式为:

类型名 变量名:位数;

变量名后为冒号,位数填写具体需要的位数,之后为分号。


35、共用体(union)又称联合体,可以用来节省内存。

标准格式为:

union 体名
{
int变量名1;
char 变良名2;
double 变量名3;
};
体名 使用该共体的共体变量名;


36、枚举使用enum工具,提供了另一种创建符号常量的方式,用来替代const,使用方法类似于结构。

枚举的格式为:
enum 枚举名{枚举成员1,枚举成员2,……};


37、枚举的特点:

①在枚举的大括号里,填写成员名,可不填写值(将自动获取默认值);

②若在声明的时候,不给枚举的成员赋值,在第一个成员的默认值为0,后面的为前一个的值加1;

③在赋值的时候,枚举的成员的值,可以相同,可以不同,可以后面比前面大,也能小;

④无需给每个枚举的成员赋值,未赋值的成员,其值为前一个成员的值加1;

⑤不能在声明之后,再次给枚举的成员赋值——只能在声明的时候同时赋值;

⑥枚举bi作为类型名时,其变量只能通过枚举bi来赋值,不能被直接赋值,例如abc = bi(8);或abc = a5th;是可行的,但是abc = 5不可行的;

⑦枚举bi作为类型名时,其变量不能为枚举相加(或相减相乘)的算数结果。例如:abc = a4th + a5th;或abc = bi(4) + bi(5);是不可行的,有其他整型的数字参与在内,也是不可行的。例如:abc = a4th + 4;

⑧当int或者其他整型、浮点类型作为类型名时,其变量可以是枚举成员或者枚举范围值的算数结果。例如:double aabc = a4th + 4;是可行的。


38、指针跟内存地址有关,他表示的是一个内存地址。

指针操作符为*和&,其中&变量名为变量的内存地址,*变量名为该内存地址的值。

可以通过修改某内存地址的值,来使得其变量的值变化。


39、

int a——int类型的变量(也是值);
int *b ——某内存地址储存了int类型的值(决定了该内存地址的宽度);
  a——变量(值);
&a和b ——地址(指针);
  *b——该内存地址的值;

在这里面,a和*b是完全等价的,是一体两面,&a和b是一个指针,指针表示的是a的地址。&b与所有的都不同,只存储a地址(一个值)的地址(&b也是一个地址)。


40、int *b; b=&a这两行代码,也可以写为int * b = &a;;但是不能写成int * b = a;也不能写成int * b;*b = a;

原因在于,初始化时,实际上可以理解为b是地址,int * b实际上是int*和b,int*的意思就是指向int类型的内存地址。而不是int 和*b。

int *b=&a;中,int *b整体,被声明为一个指针变量(因此*的存在,b是指针*b是指针变量)。而=&a;这一部分属于初始化部分(initializer),用于初始化前面的变量(b)。

 

41、int * a, b;这行代码,创造的是指针a和int变量b,即a为地址,b为一个变量。

int * a, *b;这行代码,则是两个地址,分别是指针a和指针b。

int*a只能被初始化为地址,其中a是地址,int*a,b中,a为地址,b为int变量。


42、给指针的地址赋值有两种方式。

(1)int*a,b;b=&a;将a的内存地址赋值给指针b。

(2)Int*a;a = (int*)0x0037FCB8;必须加上(int*),表示这个是一个地址,不然编译器会误以为是一个值,而非地址。另外,地址前面的0x也是不能省略的。

(int*)是强制类型转换,比如0x0037FCB8是一个值(16进制的),只有加了强制类型转换,于是二者的类型才匹配,否则左边是内存地址,右边是一个值,虽然看起来一样,但本质上二者类型不同,是不能赋值的。


43、使用new来分配内存标准格式为:

类型名 * 指针名=new 类型名;


44、在使用new来分配内存地址的时候,具体地址如何,是随机的,多个new之间,他们的地址都是不同的,不存在后面的new将前面new的内存地址覆写了。


45、(1)int* 在C++中,是一个类型,这个类型是 指向整型变量的指针。

2)a是内存地址,也是int* 类型的变量。

3)sizeof()表示的是某种类型(如int、double,这里是int*)的内存宽度,如果括号里是变量,则显示该变量类型的内存宽度。

4)而sizeof(a)表示的是 int* 类型的内存宽度,因为a是int*类型。

5)因为int*类型的内存宽度是4,所以sizeof(a)输出的结果是4。


46、在使用new的时候,可以在声明的时候使用,也可以在声明后使用。

例如:

int *a=new int;

int *a;
a = new int;//注意,需要使用a(即内存地址),而不是*a这样,类似int *a=内存地址这样

是一样的


47、在使用new请求内存之后,内存地址被占用。同样,也可以通过相反的方式释放内存,如delete。

标准的格式为:
delete 指针名;

注意,指针名前无*  ,表示只是释放该内存地址的值,但指针仍然存在。


48、在释放内存地址之后,如果要继续使用指针,就需要给指针new一个新的内存地址,方法是: 指针名=new 类型名;    


49、使用声明类型变量,在编译时为之分配内存被称为静态联编(static binding),意味着数组(或字符串,结构)是在编译时被加入内存的。

使用new,则被称为动态联编(dynamic binding),意味着数组(或其他)是在程序运行时被创建的。这种数组被称为动态数组(dynamic array)。

使用静态联编时,需要在编译阶段确定数组的长度,而动态联编,程序在运行时决定数组的长度。new相比声明类型变量,更加灵活,也更加节省内存(因为无需一直占用)。特别是面对大型数据(数组,字符串,结构)


50、创建动态数组的格式为:

类型名 *指针名=new 类型名[数组长度];
释放数组时,也需要使用delete,格式为 delete []指针名;
注意:这个时候,中括号里不加数字,则释放整个数组的内存空间。


51、①在使用动态数组时,可以用指针名代替数组名,即a为指针,a[0]为数组的第一个元素的值,而非第一个元素的地址

②*a显示的是数组第一个元素的值,而非数组全部元素的值。

③显示指针地址时,显示的是数组第一个元素的地址。

④在给指针+1时,指针的地址右移了(从B0到B8),而数组的位置没变,因此原本指向 a[0]的地址,在右移后(移动了一个double单位),指向了a[1]。这个时候,输出a[0]的命令,实际上输出的是a[1]。于是,想继续输出原本a[0]的话,就必须打a[-1]了。

⑤在移动指针之后,如果想delete指针释放内存,那么就需要将指针移动回来,例如之前是a=a+1; 那么移动回来就是a=a-1; 只有这样,才能正确释放指针。指针加1表示指针右移,减1表示指针左移,并不影响内存地址储存的值。

正因为右移和左移,所以叫指针才名副其实,因为正指的是指针指向的位置。

⑥创建指针时如果加了中括号,那么删除指针时也要加中括号。——有中括号代表数组。 只不过创建动态数组时需声明数组的元素个数,而删除的时候不用,删除只能删除整个动态数组。

⑦a[0]指的是指针所指当前位置内存地址所储存的值,a[1]指的是指针所指内存地址位置再右移(类似指针位置+1)的内存地址所储存的值。也这是为什么数组第一个元素是数组名,然后中括号里的数字为0了。因为0表示当前位置。


52、对指针加1,加的是指针类型的字节数。

例如:

int*a[5];
a+1;

这个时候,由于int是4字节,因此实际上是地址的位置加4,也就是向右移动一个int字节的宽度。

减一刚好相反,是向左。

*a+1; 是指针a所指的地址的变量+1,但是指针位置是不变的。

这说明 c++将数组名解释为地址。


53、两个指针可以相减,如代码:

#include<iostream>
 
int main()
{
using namespace std;
int a[10];
int *b, *c;
b = &a[0];
c = &a[5];
cout << "指针c为&a[5],指针b为&a[0]。指针c-指针b: c - b = " << c - b << endl;
system("pause");
return 0;
}
 
输出结果为:
5

 指针相减的结果,相当于两个元素之间指针需要偏移的距离(5个int)。


54、如果要输出地址,则需要给数组前面加&,或者给指针前面加&,才能输出地址。但两个输出的地址不同,&a是储存指针a的地址,&b是数组b的地址。a由于输出的是字符串,所以无法输出地址。只有加了(int*)或者其他(类型名*)才能将其强制转换为内存地址,若是(char*)将依然输出字符串


55、cout和C++的多数表达式中,char 数组名、char 指针以及用括号引起的字符串常量(比如"abc"),都被解释为字符串的第一个字符的地址。而输出的是字符串。只有当在之前加上 & 之后,才能显示出内存地址。


56、在使用定义的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;

#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元。
请按任意键继续. . .

57、自动变量:在函数内部声明使用,随着函数的退出而终止。使用自动存储空间,通常存储在中。

静态变量:在函数外部(程序运行期间有效)或函数内部使用关键词static(在函数消亡时保留,再次使用函数时,值为上一次退出时的值),

自由存储空间:又称为,在使用的时候分配内存,在不使用的时候可以释放他。


58、

 

普通数组

vector类

array类

备注

表示数组成员

数组名[编号]

数组名[编号]

数组名[编号]

第一个成员编号为0,后面一次类推

将一个数组赋值给另外一个数组

不可

可,需类型数相同

可,类型和成员数需相同

 

显示成员数

size(数组名)

数组名.size()

数组名.size()

 

头文件

无需

vector

array

 

名称空间

无需

std

std

 

声明时,进行初始化赋值

可,但不同于其他两类。具体见前文。

 

数组成员数变更

不可

不可

 

在数组成员之间插入新成员

不可

不可

 

删除现有数组成员

不可

不可

 

使用内存空间

使用栈(静态内存分配)

使用堆(自由存储空间)

使用栈(静态内存分配)

 

初始化成员数

常量

常量或者变量

常量

 

能否访问数组范围外的数据

例如数组名[-40]或者数组名[100]

能否使用 数组名.at(编号)检查是否在数组的范围外

不可

例如array<int, 4>a= { 1,2,3,4 };

cout << a.at(-1) << endl;

会在运行时提示出错


马上就要收拾东西回家了,不打算带电脑回家,时间有限,仓促的写了这么一篇,实际上还有一些指针的笔记没有写,待到年后若有机会就整理一下指针的笔记,至于C++笔记的二三四五的日期就不能确定了,接下来一段时间会写一些算法方面的笔记为蓝桥杯做准备,然后就准备考研啦~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值