C++阶段总结

auto类型说明符
用auto声明变量的类型,由编译器去自动分析表达式的类型,推断出变量的实际类型。
在auto变量定义时必须有初始值。
auto a; //错误:没有初始值
auto r = 1, pi = 3.14; //错误:r和pi推断出的类型不一致
注意:auto没有初始化一定错误,auto类型定义时要定义相同类型的。
decltype类型指示符
作用是选择并返回操作数的类型。
编译器会分析表达式的类型,并不真正计算表达式的值
const int ci = 0;
decltype(ci) x = 1;
//x的类型是const int
decltype(f()) y = sum;
//y的类型是函数f()的返回值类型
两者的用途
希望从初始值表达式推断出要定义的变量的类型时,用auto。
希望从表达式推断出要定义的变量的类型,但是又不想用这个表达式的值初始化该变量时,用decltype。
range-for
格式:for( declaration : expression ) statement;
例如:

int sum = 0;
for(int e : {2, 3, 5, 7, 11, 13, 17, 19})
	sum += e;
cout << sum << endl;		//输出77
int arr[] = {1, 3, 5, 7, 9};
for(auto ele : arr) {
	ele = ele * 2;					
	cout << ele << " ";				
}					// 输出:2 6 10 14 18
for(auto ele : arr)	
	cout << ele << " ";	// 输出:1 3 5 7 9 ?

后面这个代码就能很形象的表现出range-for中,ele起到对数组列表中各个元素的定义,对ele的直接操作并不会对数组各元素的数值产生影响。
指针与引用
指针
指针的定义:类型 *指针变量;
注意:指针不能保存非地址值,也不能被赋值或初始化为不同类型的地址值。
空指针:指针值为0时是一个空指针,即不指向任何对象的指针
3种生成空指针的方法

  1. `int *p1 = nullptr;

  2. `int *p2 = 0;

  3. int p3 = NULL;
    注意:不能写出int zero = 0; int *p4 = zero;
    void
    指针
    优点:可以持有任何类型的地址值,即通用指针
    缺点:不能操纵void指针指向的对象,只能传送该地址值或者和其他地址值进行比较
    不允许void指针到其他类型指针的直接赋值
    动态内存管理方法
    new
    delete
    new运算符
    在堆上动态分配空间,创建对象,并返回对象的地址
    一般将new返回的地址保存在指针变量中,以便间接访问堆上的对象
    new表达式的三种形式
    分配单个对象:new 类型 或者 new 类型(初始值)
    分配多个连续存储的对象:new 类型[数组大小]
    定位new,在指定位置分配空间:new (指针) 类型;
    例如:

    int* ip1 = new int;

//在堆上分配一个int类型的对象,返回它的地址

int* pi = new (buf) int;

注意:使用定位new,必须包含标准库头文件
堆上的空间在使用后必须释放,否则会造成内存泄漏
即动态内存空间使用后未回收,导致一直被占据
所有new所分配的空间有delete进行释放
释放new分配的单个对象的delete形式
delete 指针;
释放new分配的数组的delete形式
delete[] 指针;
定位new没有对应的delete表达式
空悬指针
执行delete运算后,指针ip指向的空间被释放,不能再使用ip指向的内存,但是ip这个指针变量自己的存储空间不受影响
delete后的ip不是空指针,而是“空悬指针”,即指向不确定的单元
delete之后,继续通过ip间接使用这个单元是非法的,会引起不可预料的运行错误
左值引用
int &refVal = ival;
左值引用的初始化和一般变量的初始化不同
一般在初始化变量时,初始值会被复制到新建的对象中
定义引用时,程序把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用
引用一旦初始化,就不能再指向其他的对象,对左值引用的所有操作都会被应用在它所指向的对象上。左值引用的初始化和一般变量的初始化不同,一旦初始化完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重新绑定到另外一个对象,所以引用必须初始化。
右值引用
生成右值的表达式
返回非引用类型的函数,连同算术、关系、位运算、后缀自增/自减运算符;字面值常量、要求转换的表达式
类型 &&右值引用变量 = 右值表达式;
const限定指针
指向const对象的指针(非const )
const type *cp; 或者type const *cp;
cp是指向常量的指针,它所指向的内存中的内容不可以改变,即*cp的值不能改变。
指向非const对象的const指针
type* const cp = initAddressValue;
cp是常量指针,初始化后值不能改变,指向固定的单元。
指向const对象的const指针
结构体
结构体把一组来自不同类型的数据组合在一起构成复合类型,其中的每个数据都是结构体的成员。
结构体由关键字struct定义,语法形式:
struct 结构体类型名
{
 成员声明;
};
枚举
枚举类型定义了一组命名的整数常量,以提高代码的可读性, 例如
enum Light{ red, green, yellow};
1.可以使用未命名的枚举类型定义常量。例如:
enum {False,True};。
2.enum定义的枚举在C++11标准中被称为不限定作用域的枚举类型。C++11引入了限定作用域的枚举类型,用关键字enum class或enum struct定义。
3.在不限定作用域的枚举类型中,枚举成员的作用域与枚举类型本身的作用域相同。
标准库类型string
string表示可变长度的字符序列。使用需要包含头文件< string>。
简单使用:
#include< iostream>
#include< string>
using namespace std;
int main()
{sting s1,s2;
string s3=“hello,world”;
string s4(“I am”);
s2=“Today”;//两种赋值
s1=s3+" "+s4;//字符串连接
s1+=“5”;}//末尾追加
1.s.empty() s为空返回1,否则返回; s.size() 返回s中的字符个数; s[n] 返回s中第n个字符的引用,n从0开始计。
标准库类型vector
vector表示对象的集合,所有对象类型相同。vector这样容纳这其他对象的对象被称为容器。vector是长度可变的向量,比数组用起来更方便更快捷。使用需要包含头文件< vector>。
语法形式:
vector <元素类型> 变量名;
几种初始化类型:
1.vector< T>v2(v1) v2中包含v1所有元素的副本。
2.vector< T>v2=v1 等价于v2(v1)。
3.vector< T>v3(n,val) v3包含n个重复的元素,每个元素的值都是val。
4.vector< T>v4(n) v4包含着n个重复执行值初始化的元素。
5.vector< T>v5{a,b,c…} 对每一个进行赋值。大括号前有无赋值号效果相同。
vector支持的几种操作:
v.empty() 是否为空。
v.size() 返回元素个数。
v.push_back(t) 末尾添加一个元素t。 v.pop_back() 末尾删除一个元素。
迭代器
类似于指针类型,间接访问对象。迭代器在容器或string对象上使用,所以迭代器指向的对象时容器中的元素或string中的字符。使用迭代器可以访问容器中的某个元素,也可以在容器上移动。迭代器只有在指向某个元素或指向最后一个元素的下一个位置是才是有效的。

1.标准库容器用iterator和const_iterator表示迭代器类型,例如:
vector< int >::iterator a1; //a1能读写vector< int >的元素。
string::iterator a2; //a2能读写string对象中的字符。
加了const_就变成了只读不写。
2.迭代器支持的运算符
*iter 解引用,返回所指元素的引用
iter->mem 解引用iter并获取该元素的成员mem,等价于(*iter).mem.
++iter 指向下一个元素 --iter指向上一个元素。
iter1==iter2 判断两者是否相同,
istringstream:istream的派生类,用来从string对象中读取数据。
ostringstream:ostream的派生类,用来向string对象写入格式化的内容。
stringstream:iostream的派生类,既可以读数据也可以写数据。
函数定义
返回类型、函数名、参数列表、函数体构成了函数定义。语法形式为:
返回类型 函数名(函数列表){函数体}
1.函数的参数列表不能省略。如果函数没有任何参数,可以用空参数或void参数表示。例如:
int foo() 隐含定义空形参表;
int foo (void) 与上面等效。
2.参数列表由逗号分隔的形参类型列表构成,每个形参类型之后跟一个可选的形参名字。如果形参没有名字,则该参数不能再函数中使用。
参数传递
1.按值传递
2.传引用
3.传指针
按值传递简单方便适用于数据较小的情况,只能返回一次值,不能反映形参的变化情况。不能使实参交换,此时就用到下面两个传指针和传引用了。
函数重载
对不同类型的数据执行相同的一般性动作,表达相同的概念,这就用到函数重载。
C++的函数重载允许多个函数共享一个函数名,但对不同类型进行不同操作。
重载函数:函数名相同,功能类似,参数不同。例如:
void print(const int *b,const *e){…}
void print(int ia[ ],size_t size){…}
void print(const char *cp){…}
重载函数调用三种结果:
1.编译器找到一个与实参最佳匹配的函数,生成调用该函数的代码。
2.找不到任何一个函数与调用的实参匹配,编译器报告无匹配的错误信息。
3.编译器找到了多个与调用匹配的函数,而且匹配的程度一样好,此时发生二义性调用错误。
.存储类别和存储空间分配
1.静态分配
系统为每个程序开辟一个固定的全局静态存储区,静态分配就在这个固定区域为变量分配空间。
2.自动分配
程序运行后,系统将微程序开辟一块成为栈的活动存储区。自动分配在栈中为变量临时分配空间
3.动态分配
动态分配是指利用一个叫做堆的内存块为变量分配空间。动态分配是一个完全由程序员本身控制内存使用的分配方式。

猜你喜欢

转载自blog.csdn.net/nihaibeizhanyong/article/details/88777664