C++中易记混知识点总结(长期更新)

标签: C 易记混知识点 知识点
2065人阅读 评论(0) 收藏 举报
分类:

C++中易记混知识点总结(长期更新)

1、const指针和引用

const int &a;//引用对象为const,但实际上只是a一厢情愿为const引用,应用对象可以为普通变量,但a仍不能改变其值(特别注意在函数形参中的使用)。

const int *a;//指向常量的指针,和上面常量引用一样是一厢情愿,注意从右向左看,a首先是一个指针,指向一个const int。

int *const a=&cc;//从右往左看,a首先是一个常对象,其次是一个指针,说明是一个常指针,常指针必须初始化,之后便不能改变。引用不是对象,不存在本身是const的引用。

不能将一个指向(引用)常量的指针(引用)赋值给一个普通指针(引用),这样有可能造成所指(引用)对象改变。

2、复杂度数组、函数声明

int *p[10];//从左往右看,首先由[10]看出p是一个数组,再看*可以知道数组中存储的是指向int的指针,可以理解为(int *) p[10],此语句定义的是一个数组。

int (*p)[10]=&cc;//先从括号内向外,p前面有*,在定义中一定是指针,所以p是指向数组的指针,数组内容为int类型,此条语句定义的就是一个指针p。

int &p[10];//没有这种写法

int (&p) [10];//数组本身是对象,所以允许定义数组的指针和引用,从内向外看,p前面有&,所以p为引用,是数组的引用。

int *p();//从右往左看,表示函数p返回值是(int*)。

int (*p)();//从内往外,p是一个指针,指向一个函数。

定义一个返回指针且指针指向一个数组的函数有两种方法:

一是使用类型别名

typedef int arrT[10];//arrT是一个类型别名,表示的类型是含有10个整数的数组,等同于using arrT=int[10]

arrT* func(int i);//此函数返回指针,指向一个arrT类型,也就是一个含10个整数的数组。

二是如下

int (*func(int i))[10];//从内向外,func返回一个指针,(*func(int i))解引用为一个数组名,所以此语句定义一个返回指针的函数,指针指向一个int 数组。

int *(&array) [10] =ptrs;//int *ptrs[10],从内向外看,array是一个引用,引用一个数组,数组内容为(int *)类型。此语句定义的是array,所以初始化给的是ptrs。

3、指向数组的指针

int *matrix[10];//定义了一个由十个int指针组成的数组。

int (*matrix) [10];//定义了一个指针,指向含有10个整数的数组。

int matrix[] [10];//同上一个,matrix[]==(*matrix)。

4、类模板和模板类

一个类模板(也称为类属类或类生成类)允许用户为类定义一种模式,使得类中的某些数据成员、默认成员函数的参数、某些成员函数的返回值,能够取任意类型(包括系统预定义的和用户自定义的)。模板类其实是类模板的实例化产物,如vector和initializer_list都是类模板,而vector<int>是一个模板类。函数模板和模板函数区别类似。

5、string的一些小知识

string的size()函数返回值类型为string::size_type,这是一种能保存任意string长度的无符号整数,时常可以定义为auto n=nums.size()。

比较两个string对象,==需要长度内容完全一样,如果两个string长度不同,短的string的每个字符都与长string对应位置的字符相同,则短的<长的,如果在对应位置不一致,则比较的是第一个不一致字符的大小。

如:string a="Hello",string b="Hiya",则b>a.

字面值和string对象相加,必须保证加号的一边为string对象,有括号的按优先级来看,如:

string a="abc"

string b=a+", "是正确的

string c="sd"+"sdd"是错误的

string d=(a+"sd")+"se"括号内生成的是string对象

6、string和int的相互转换

有两种方法,一种是采用stringstream,包含在头文件sstream里。

stringstream stream;

string s;

int n;

stream<<s;

stream>>n;

第二种是采用C++11的新特性,string to_string(int a),int stoi(string a);

int n=2;

string s=to_string(n);

int a=stoi(s);

7、fstream和sstream

头文件fstream中定义了三个类fstream,ofstream,itstream,分别用来读写文件、写文件、读文件,下面代码实现了从文件中读取字符串,并直接转化为int数据,文件流中默认以空格作为间隔:

ifstream FILE;
	FILE.open("execute.stdin");
	vector<int> nums;
	int a;
	while(!FILE.eof()){
		FILE>>a;
		nums.push_back(a);
	}
FILE文件流从字符串中每次读入一个字符串给a,并根据a的类型直接将类型转化,如果FILE文件读到末尾,则流的状态会变成EOF,此时读写操作都将不成功。

类似的,头文件sstream中定义了三个类stringstream、istringstream、ostringstream,定义一个stringstream对象ss,和一个string a="sadf",利用ss的构造函数,可以用stringstream ss(a),将ss初始化,此时定义一个string temp,可以利用一下代码依次将ss中的string传递给temp:

while(!ss.eof())
     ss>>temp;
也可以写成while(ss>>temp)
如果后续需要将temp转化为int,可以考虑定义一个stringstream s2,利用以下代码实现:

int a;
s2<<temp;
s2>>a;

此时要注意,由于ss只有一个元素,因此在s2>>a后,s2的状态将被置为eof,不能进行任何读入读出操作,所以如果上述三行代码在循环中实现多次string到int的转化,s2将会在第一次之后失效。解决办法是使用s2.clear(),清除它的EOF状态,同时由于s2的缓存区会逐步增大(不是eof时),为了减少内存消耗,需要每次读取完毕后调用s2.str(""),将s2的缓存清空,上面两句代码都是必不可少的。为了避免上述情况,可以利用stoi和to_string来完成int和string的转化。

8、string的基本操作

string也是顺序容器,所以拥有顺序容器的许多基本操作。同时还有一些特有的操作,如截取、替换、查找。

截取:s.substr(pos,n),其中pos表示下标,不是迭代器,n表示截取的数量,返回提取的那一段,如果想删除某一段,可以将截取后的一段重新赋值给原字符串。

替换:s.replace(pos,n,s1),用s1替换s从位置pos开始的n个字符。

查找:s.find(a,pos,n),是从pos开始找目标a,a可以是一个string、char *、char,n是查找位数,可以不要。返回查找到的位置,没有找到返回-1

s.find_first_of、s.find_last_of。

翻转:algorithm头文件中,reverse(s.begin(),s.end()),此函数对其他容器也适用。

9、fstream补充知识

定义一个文件流,同时将它与一个文件关联,fstream("mytext.txt"),该语句默认用in和out模式使用文件,默认情况下,out模式打开文件默认会截断,也就是说out模式下文件内容会被丢弃,阻止其清空文件的方法是显式设置app模式,fstream("mytext.txt",ios::out|ios::app)。ios比fstream高级,可以通用。

在使用中最好将读写操作分别用ifstream和ofstream流来操作,这样可以避免文件模式的设置。如果一定要用同一个流,需要控制读、写的标记,当需要写的时候,要利用f.seekp(offset,from)设置写标记,from可以取fstream::end、beg、cur,如果用fstream::end,表示从文件末尾开始读。f.seekg()表示设置读位置,tellp()表示返回写位置,tellg()表示返回读位置。

fstream ii("test.txt",ios::in|ios::out|ios::app);
	string k;
	ii >> k;
	ii.seekp(0,fstream::end);
	ii << "111" << endl;
上述代码中,test.txt中已有内容,向k中读入后,如果直接再向文件写入,写入会失败,此时需要将写标记移动到文件尾,然后写入成功。

10、关联容器不能采用sort排序

set、map内部采用红黑树,内部存储元素是pair,不是线性存储的。set和map对key进行了排序,而需要对value排序,必须将map转移到线性容器如vector等中,不能使用sort。

11、求任意对数的方法

C++中有两个对数log(ln)和log10,对于任意对数可以用上述对数相除得到,但注意用log相除可能会由于四舍五入造成偏差,所以用log10比较好。

12、关联容器迭代器用法

由于关联容器不是线性存储,因此其迭代器用法和string、vector等线性容器有所不同。如对于map s,s.begin(),要遍历下一容器只能++s.begin(),不能够s.begin()+1,因此也没有s.begin()+n的方法。

13、变量是在堆上还是栈上

一个程序内存分为五类,栈、堆、全局(静态)区、文字常量区、代码区。

栈由编译器自动释放,用于存储局部变量,函数参数等,是高地址向低地址扩展的连续内存,一般1M到2M,超出会报overflow。栈上的东西出了作用域会自动回收。如在函数中定义int a[1000][1000]便会超出。

堆是程序员自己分配释放,是用链表连接的从低到高的不连续内存区,灵活度高,容量大,但是不如栈快。用new或malloc动态分配的空间都在堆上。例如char *p=new char[2]

如上述语句在函数中,则指针p本身(一个地址)存储在栈中,而它指向的一段内存则是在堆中,同样由于vector内部采用new,因此vector<int> a(100,0),的对象a本身是在栈中(这个对象肯定包含了一个指向堆中的指针),但是它的内容,100个int则都是在堆中。对于类的对象,有如下例子阐述对象的成员是在堆中还是栈中:

class A{

vector<int> a(100,0);

};

int main(){

A b;

A *c=new A;

}

对象的成员是在堆中或栈中取决于对象本身,如果是在函数中且非动态分配内存,则对象的成员在栈中,在本例中b的成员a在栈中,但是它的100个int是在堆中,这是决定于vector内部,而c指向的对象的成员a在堆中,其100个int也在堆中。

  • 全局变量和static均在静态区
  • 字符串常量等在文字常量区

14、heap操作和priority_queue

heap操作定义在algorithm中,是一个操作容器的函数,priority_queue不是STL标准容器,底层采用了heap算法,而它们保存数据的容器都是vector或deque。

heap操作直接对vector进行,将存在vector中的一个完全二叉树(每一层从左到右放入vector中)进行建堆等操作。heap操作有如下几个:

int main () {
  int myints[] = {10,20,30,5,15};
  std::vector<int> v(myints,myints+5);

  std::make_heap (v.begin(),v.end());
  std::cout << "initial max heap   : " << v.front() << '\n';

  std::pop_heap (v.begin(),v.end()); v.pop_back();
  std::cout << "max heap after pop : " << v.front() << '\n';

  v.push_back(99); std::push_heap (v.begin(),v.end());
  std::cout << "max heap after push: " << v.front() << '\n';

  std::sort_heap (v.begin(),v.end());

  std::cout << "final sorted range :";
  for (unsigned i=0; i<v.size(); i++)
    std::cout << ' ' << v[i];

  std::cout << '\n';

  return 0;
}

  • make_heap(begin,end),函数参数为一个vector或者deque的前后迭代器,默认less模式,也就是第一个元素是在大元素的最大堆。如要采用最小堆,第三个参数为greater<type> (),是重载的().
  • pop_heap(begin,end),将一个已建堆的vector的第一个元素放到end之前,并将前面元素恢复堆特性,此时最大(最小)元素并没有pop出,需要用vector.pop_back()将元素弹出。
  • push_heap(begin,end)是对一个刚加入新元素的堆,重建它的堆特性。
  • sort_heap(begin,end)是多次进行pop_heap操作,最终完成一个排序,最大堆模式下得到的排序为升序。

priority_queue的用法如下:

它除了有queue的一些用法,还有几个特殊用法。

  • priority<type,container type,compare type> qp;type表示优先队列中元素的类型,可以是自定义类,第二个元素为容器的类别,如vector<type>,第三个是一个比较函数类,默认为less,也就是采用最大堆,最终排序为升序,先出大的元素。如果要用最小优先队列,则需要加上greater<type>,注意这里没有括号,如果type是自定义类,则需要单独写比较类,如下,这里是从队列的角度看的,需要一个递减序列,用最小堆实现。这里重构了一个().

class myCompare{
        public:
        bool operator()(Node &a,Node &b){
            return a.len>b.len;
        }   
    };


  • pq.empty(),pq.top()取最大(最小)元素,pq.pop(),pq.push()。

15、malloc() free()和new delete的区别

  • malloc的参数是字节数,必须用sizeof给定类型的大小,且返回void *类型,必须强制转化为相应指针类型,如char *p=(char *) malloc(sizeof(char)*128),这语句分配了128个char的内存,在堆中。而new的用法为char *p=new char[128]。
  • 对于自定义类,new和delete能自动调用类的构造和析构,malloc不行,但C语言只支持malloc
  • 注意不管是new还是malloc,如果指针是局部变量,它就在栈,但是申请的空间是在堆。malloc采用空闲链表机制,延表寻找大小满足所需的内存块,将需要的大小分出,留下剩余的小部分继续在表中,这样最终就会造成表中内内存均是碎块,申请内存失败,返回NULL指针。
  • free之后是指针所指内存释放,指针并没有,指针是一个变量,只有随函数完毕而销毁。



查看评论

C++重点知识点总结及习题

  • 2016年01月29日 14:30
  • 865KB
  • 下载

java知识容易混淆的知识点总结

java知识容易混淆的知识点总结 1.java是强类型的语言、区分大小,数组也是对象,一旦确定数组的类型,里面就只能存放一种类型的数据; 2.新建的对象都被存放到堆上,如果没有引用,会很快...
  • liuwenbiao1203
  • liuwenbiao1203
  • 2016-07-28 08:46:08
  • 364

c语言知识点总结【完美版】

  • 2013年07月11日 10:32
  • 134KB
  • 下载

C++知识点汇总

C++笔记(一)变量与函数 变量声明:extern int i;函数声明:extern float f(float);float f(float); //extern在此不是必须的float f(fl...
  • wave_1102
  • wave_1102
  • 2008-02-22 22:32:00
  • 9284

C语言易混易错知识点

1、声明可变长数组 Int a[*];   // 可变长数组不是动态的,可以变化的是数组大小 这样的写法不能用在全局或者共用体里 2、字符常量 字符常量只能用单引号括起来,不能用双引号。 字符常量只...
  • sinat_14866987
  • sinat_14866987
  • 2015-05-14 15:28:07
  • 702

C++的一些知识点总结

本文的主要内容来自孙鑫的《VC++深入详解》和侯俊杰的《sh
  • xiaqunfeng123
  • xiaqunfeng123
  • 2014-06-24 14:54:08
  • 1552

c++重要知识点总结

1、内存分配的方式: 分配方式有三种: 1.静态存储区,是在程序编译时就已经分配好内存,在整个运行期间都存在,如全局变量、常量。 2.栈上分配,函数内的局部变量就是从栈上分配的,但分配的内存容量...
  • houzuoxin
  • houzuoxin
  • 2014-08-31 08:31:39
  • 2634

C/C++重要知识点总结

一、程序的在内存中的存储空间 (1)代码区:存放二进制代码的区域; (2)文本常量区:a、字符串;b、const全局变量,而const局部变量存放在栈中; (3)全局变量区(静态变量区):a、data...
  • tfygg
  • tfygg
  • 2015-09-11 23:48:23
  • 1005

C++ 类的知识点总结

(1)在类的定义过程中,不使用public与private声明的话,类中的数据和成员函数都默认为私有的。(2)类中的成员限定访问符:public与private是可以多次出现的,而且不限定先后顺序。(...
  • chaipp0607
  • chaipp0607
  • 2017-03-26 14:15:12
  • 914

C++ 程序设计基本概念 知识点 小结

知识点包括:全局变量的二次赋值;计算转化为二进制后,数字中 1 的数量;用一个非循环表达式判断一个数是否是2的N次方;逻辑运算与位逻辑运算;printf 输入表达式的执行顺序;位运算判断输入参数是否为...
  • u013630349
  • u013630349
  • 2015-08-12 14:19:44
  • 1431
    个人资料
    持之以恒
    等级:
    访问量: 1万+
    积分: 959
    排名: 5万+
    文章分类
    最新评论