C++复合类型及函数学习总结

C++复合类型及函数学习总结
复合类型
复合类型是指在其他类型的基础上定义的类型。C++语言内置的复合类型分为:指针、引用、数组、枚举、结构体、共用体。
1、程序运行时,代码和需要的数据都被存储在内存中。内存是有序的字节序列,每个字节都有唯一的地址,使用这个地址就可以确定字节的位置,用以存获取数据。程序中定义的变量会被分配一定的内存单元,当需要存取这个值时,可以通过变量的名字访问这块内存。除了通过名字直接访问变量的内存单元,也可以使用内存地址找到存放数据元,间接访问其中的内容。指针可以持有对象的地址,引用则是对象的别名。
指针:
它持有一个对象的地址,称为指针“指向”这个对象。定义指针:char* a;当定义两个指针时:char* a,b;每个变量名前面都要有,*a表示对存放指针地址的指针.int a=120;int b=&a;&即取地址符。即b为a的地址;sizeof()用来计算所占内存大小,同类型的指针可以进行相等和不相等的比较,地址若相同,则它们相等;反之不相等。这里的地址值相同(==)或不相等(!=)的比较操作,比较的结果是布尔类型。自增、自减运算同样适用于指针。now和delete
在C++中,对象可以静态分配空间,即编译器在处理程序源代码时分配内存,也可以动态分配空间,即程序运行时调用运行时刻库函数来分配内存。这两种内存分配方法的主要差异在于效率和灵活性。静态内存分配是在程序执行之前进行的,因而效率比较高,但目的元素却需要动态内存分配的灵活性。是缺乏灵活性,因为它要求程序在执行之前就知道所需内存的类型和数量。
(1)静态对象是有名字的变量,可以直接对其进行操作;而动态对象没有名字,要通由程序员显式地管理。
(2)静态对象的空间分配与释放由编译器自动处理,动态对象的空间分配与释放必须程序由程序员显式的管理。
程序使用动态内存出于以下三种原因之一:
(1)程序不知道自己需要使用多少对象
(2)程序不知道所需对象的准确类型
(3)程序需要在多个对象间共享数据
C++语言则通过new和delete两个运算符来进行动态存储空间的管理。new在动态内存中为对象分配空间,并返回一个指向该对象的指针,可以选择对对象进行初始化。 delete接受一个动态对象的指针,销毁指针指向的对象,并释放与之关联的内存。New 类型 New 类型[数组大小]new (指针)类型;delete 指针delete []指针。
引用:
分为左值引用和右值引用。左值引用可以理解为给对象起了个小名,操作符是&与指针不同的是&在赋值号左边。而右值引用是对赋值号右侧的常量的操作,是在赋值号左侧加两个&;左值引用:类型&引用名=初始值;右值引用:类型&&右值引用变量=右值表达式;
结构体:
结构体把来自一组不同的数据组合在一起构成复合类型,其中的每个数据都是结构体的成员。结构体由关键字struct; 结构体的成员不能独立使用必级由结构体类型的变量通过成员选择运算符“.”来 者由结构体类型的指针通“->”运算符选择。定义绍构体类型之后,就可以创建该类型的变量。
枚举:
关键字:enum;定义:enum {false,ture},即对false和ture关联0 1;枚举类型不能迭代。
数组:
使用数组时一般会转换为指针ia是一个int类型的指针常量,ia和&ia[0]都表示数组第一个元素的地址可以使用指针对数组进行访问。一维数组元素在内存中按下标顺序依次存放
Int
pb=begin(arr),*pe=end(arr);
While(pb!=pe&&*pb>=0)
++pb;
for(auto p = begin(arr); p!= end(arr); ++p)
cout << p << “\t”;
一维数组a[n]的元素a[i]在内存中地址是a+i。
多维数组在内存中按行序存储
二维数组a[m][n]的元素a[i][j] 在内存中的地址是a+(i
n+j)
指向数组的指针可以执行解引用、自增、自减、加或减一个整数、两个指针相减、比较等运算
指针加或减一个整数n,结果仍是指针
新指针指向的元素与原来的指针相比前进或后退了n 个位置
两个指针相减的结果是它们之间的距离
参与运算的两个指针必须指向同一个数组中的元素
两个指针如果指向同一个数组的元素,可以利用关系运算符对其进行比较
标准库类型string
//默认初始化:
string s1; //s1是一个空串,没有任何内容
//拷贝初始化:把=右边的初始值复制到左边新创建的对象中
string s2 = s1; // s2是s1的副本
string s3 = “hello”; //s3是这个字符串字面值的副本
//直接初始化:初始值可以有一个或多个
string s4(“welcome”); //s4是这个字符串字面值的副本
string s5(5, ‘a’); //s5的内容是aaaaa

输入空格不行,遇到空格就结束。
如果希望在读取的字符串中能保留输入时的空白符,使用 getline()函数。 Getline()函数带两个参数:输入流对象和存放读入字符串的 string对象。函数从指定的输入流中读取内容,直到遇到换行符为止;然后将所读的内容存入指定的 string对象中。需要注意的是流中的换行符也被读取了,但是不存入 string对象,而是丢弃了。 getline遇到换行符就结束读取操作并返回结果,所以,如果一开始就是换行符,所得的结果就是一个空 string
Getline()返回输入流参数,所以也可以用 getline()的结果作为条件。例如
//每次读取一行文本,直到文件结束
string line;
while(getline(cin, line))
cout << line << endl;
//每次读取一行文本,输出非空的行
string line;
while(getline(cin, line))
if(!line.empty()) //line不为空,输出
cout << line << endl;
//每次读取一行文本,输出长度超过80个字符的行
string line;
while(getline(cin, line))
if(line.size() > 80)
//字符串长度的类型
string line = “hello”;
string::size_type len1 = line.size();
auto len2 = line.size();
decltype(line.size()) len3 = 0;
Const限定指针和引用:
Auto
当使用数组名作为一个auto 变量的初始值时,得到的类型是指针而不是数组
decltype(数组名)返回的是数组类型:大小和元素类型

Vector
标准库类型 vector表示对象的集合,其中所有对象的类型都相同,夏以通过索引访各个对象。像 vector这样容纳着其他对象的对象被称为容器。 vector是长度可变的向量,为内置数组提供了一种更灵活、更高效的替代表示。要使用 vector,必须包含头文件。 vector可以像数组一样使用,还可以按标准模板库(STL)习惯使用。
统计文本中的字母和数字:
#include
#include
#include
using namespace std;
int main(){
string line;
cout << “Enter a line of text:” << endl;
getline(cin, line);
string::size_type cntLetter = 0, cntDigit = 0;
for(auto c : line)
if(isalpha©) ++cntLetter;
else if(isdigit©) ++cntDigit;
cout << "letter is " << cntLetter << endl;
cout << "digit is " << cntDigit << endl;
}
用下标运算符可以访问string对象中指定位置的字符
string对象s的下标范围从0到s.size()-1
下标变量的类型是string::size_type

vector的大小可以动态变化

可以在初始化时指定vector对象的大小和初始值
常见用法是创建一个空vector,根据需要动态添加元素
push_back()
将一个值添加到vector的末尾,并使vector的大小增加
pop_back()
删除vector对象末尾的元素
push_back()函数向vector中添加元素时,会创建参数的一个副本,添加的是这个新值而不是原始值
使用pop_back()函数删除vector对象中的元素时,要先检测对象是否为空
如果要用循环向vector对象中添加元素,不能使用范围for,范围for不能改变所遍历的容器的大小
不能用下标运算符向vector中添加元素
下标运算符只能访问已经存在的元素
迭代器:
迭代器类似于指针类型,提供对对象的间接访问
迭代器在容器或string对象上使用,指向的对象是容器中的元素或string中的字符
访问标准容器的元素的通用方法是使用迭代器
使用迭代器可以访问容器中的某个元素,也可以在容器上移动
标准库容器迭代器的类型
iterator、const_iterator
begin()和end() 操作返回容器对象上的迭代器
begin()返回指向第一个元素或字符的迭代器
end()则返回指示容器或string的最后一个元素的下一个位置的迭代器
如果容器为空,begin()和end()返回同一个迭代器,都是尾迭代器
cbegin()和cend()函数返回const_iterator
//利用迭代器将s中的第一个词改成大写形式
string s = “Hello, World!”;
auto it = s.begin();
while (it != s.end() && !isspace(*it)) {
*it = toupper(*it);
++it;
}
cout << s << endl;
//输出:HELLO, World!
使用vector和string的代码比使用内置数组和字符数组更简洁、更高效
string和vector都是可变长度的
灵活,编写相应的代码比使用动态内存管理更容易且不易出错
string和vector是对象
封装带来的简单性,对接口编程
虽然不知道string类和vector类型具体是如何实现的,但是并不妨碍正确地使用它们
C++标准库中的文件流
ifstream类:用来输入(读文件)的文件流
ofstream类:用来输出(写文件)的文件流
fstream类:把文件连接到流对象用来输入和输出
文件读写可以使用与终端I/O相同的运算符和操作
使用文件流要包含头文件
继承关系
istream(ostream、iostream)的操作在ifstream(ofstream、fstream)中都可以使用
1)新建一个文件流对象
读文件用ifstream,写文件用ofstream;
(2)把文件流对象和文件关联起来
打开文件,使用文件流的open函数;
可以指定打开文件的模式
(3)操作文件流
使用与终端I/O相同的操作读写文件
(4)关闭文件流
使用文件流的close函数
字符串流用于内存I/O,即在字符串上进行I/O操作
istringstream:从string对象中读取数据
ostringstream:向string对象写入格式化的内容
stringstream:从字符串读取数据,将数据写入字符串
使用时包含标准库头文件
在定义时直接用string对象初始化
strm.str(s),将字符串s复制到字符串流strm中,返回void
strm.str(),返回字符串流strm中保存的字符串的副本
输入缓冲区
从输入流一次性读取一大块数据,以字符串形式保存在istringstream对象中,再用适当的输入操作逐项从istringstream对象中提取各个数据项
输出格式化
将所有要输出的内容先用输出操作写到ostringstream对象上,再一次性的将这个ostringstream对象中保存的字符串写入输出流

函数
函数是一个命名的代码块,通过调用函数可以执行相应的代码
用来实现各种算法,完成特定的任务
库函数,程序员自定义的函数
C++程序由函数构成,函数之间通过传递参数和返回值进行通信
编写并使用自己的函数
定义函数、声明函数、调用函数
参数传递是指用函数调用的实参来初始化函数形参存储区的过程
函数的形参是局部对象,仅在函数的作用域内可见
每次调用函数时,会创建形参变量,并用传入的实参初始化形参
形参的类型决定了实参初始化形参的方式
如果形参是引用类型,形参将绑定到对应的实参上
否则,将实参的值复制后赋给形参
传值,按值传递参数
当实参的值被复制给形参时,形参和实参是两个独立的对象,实参被称为按值传递,或传值调用函数
C++的默认参数传递方式
传指针:使用指针参数是传地址值
函数调用和返回
函数调用会使程序的控制权传递给被调函数,而当前活动函数的执行被挂起
当被调函数执行完成时,主调函数从调用语句之后的语句恢复执行
函数在执行完函数体的最后一条语句或遇到return语句时返回
默认情况下,函数的返回值是按值传递的
当参数是引用时,函数接收的是实参的左值而不是值的副本,即形参是实参的引用,或者说是别名函数操纵的形参是实参的别名,因而可以改变实参的值void rswap(int& rv1, int& rv2){
int t;
t = rv1;
rv1 = rv2;
rv2 = t;
}
int main(){
int ival1 = 10;
int ival2 = 20;
cout << ival1 << " " << ival2 <<endl;
rswap(ival1,ival2);
cout << ival1 << " " << ival2 <<endl;
}
传值、传指针还是传引用?
对于内置类型的小对象,传值的方式更简单直接
如果想在函数内改变实参,使用传引用或传指针的方式
传指针的语法比引用复杂一些,但使用起来更清晰明确
对于类类型的对象,尽量使用引用传递参数,效率更高
使用const限定可以避免实参被修改
函数的执行结果由return语句返回
return语句结束当前正在执行的函数,将控制权返回给函数的调用者
return语句有两种形式:
return;
用在返回类型为void的函数中,不是必需的
return 表达式;
函数的返回类型决定了函数调用表达式的类型,以及是否是左值
调用一个返回引用的函数得到左值
其他返回类型得到右值
返回引用的函数调用表达式可以作为左值使用
可以为返回类型是非const引用的函数的结果赋值
对引用返回值的修改会改变实际返回的对象,为了避免这种情况,可以将返回值声明为const
main函数的返回类型为int,作为程序返回给系统的值
main()函数返回0表示执行成功,返回非0值表示执行失败,其中非0值的具体含义依机器而定。
允许main函数没有return语句直接结束
如果控制到达了main函数的结尾处而没有return语句,编译器隐式地插入一条表示返回0的return语句
C++函数重载机制
多个函数可以共享同一个函数名,针对不同的参数类型提供不同的操作
重载函数
如果同一个作用域内的几个函数名字相同但形参列表不同,则它们是重载函数
void print(const int *b, const int *e){…}
void print(const int ia[], size_t size){…}
void print(const char cp){…}
重载函数的参数表必须不同
或参数个数不同,或参数类型不同
返回类型不能区分两个重载函数
因为调用函数时可以忽略函数的返回值
int foo(int a); // 声明f(int)
int x = foo(5); // 正确,保存返回值
foo(10); // 正确,不保存返回值
//加上下面的错误声明
void foo(int b); //错误声明
foo(10); //不能确定调用那一个foo
注意点:
空指针和空闲指针。
空指针
指针值为0时是一个空指针,即不指向任何对象的指针
表示空指针的3种方法
0
nullptr
C++11
预处理常量NULL

执行delete运算后,指针ip指向的空间被释放,不能再使用ip指向的内存,但是ip这个指针变量自己的存储空间不受影响
delete后的ip不是空指针,而是“空悬指针”,即指向不确定的单元
delete之后,继续通过ip间接使用这个单元是非法的,会引起不可预料的运行错误
Void
指针
可以持有任何类型的地址值,即通用指针
相关的值是个地址,但是该地址保存的对象类型不知道

不能操纵void指针指向的对象,只能传送该地址值或者和其他地址值进行比较
不允许void指针到其他类型指针的直接赋值
区分
是C++标准库头文件,包含了拟容器class std::string的声明(不过class string事实上只是basic_string的typedef),用于字符串操作。
是C标准库头文件<string.h>的C++标准库版本,包含了C风格字符串(NUL即’\0’结尾字符串)相关的一些类型和函数的声明,例如strcmp、strchr、strstr等。和<string.h>的最大区别在于,其中声明的名称都是位于std命名空间中的,而不是后者的全局命名空间。
看定义就知道了,string是新标准,定义了namespace std;而cstring虽然也是新标,但是定义中包含的是string.h。
感想:
学习了C++后可以很明显的感觉出,现在学习的与上学期的东西不一样了,面向对象程序设计,感觉从原来只是为了做题目敲代码到现在可以做出给别人用的软件,学习的函数内容也与上学期不一样,由关注点在值上,到现在有多种方法来灵活运用函数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值