C++笔记(细节)

目录

细节

堆栈

关于调试

关于new和构造

读写文件或数组

输入输出

关于重载

关于模板

类型转换

 关于const

字符串与int、double转换

访问权限

C语言独有

string类

内置数据结构

优先队列

仿函数与谓词

关于lambda

内建仿函数

STL算法

遍历

查找

排序

拷贝、替换

算数生成(包含numeric)

集合


细节

Short:2  int:4  long:4  long long:8  float:4  double:8  char:1  bool:1  指针:4

unsigned   int  : 0~4294967295   
int :  2147483648~2147483647 
unsigned long :0~4294967295
long :  2147483648~2147483647

long long(__int64):-9223372036854775808~9223372036854775807
unsigned long long(unsigned __int64):0~1844674407370955161

注意有模(MOD)的时候定义一个const变量,指数可以用1e9+7(即pow(10,9)+7)的格式表示,而数据的表示范围如果达到1e9,一般都要用long long

类成员变量所占空间对齐

3e2=3x102

memset()函数原型是extern void *memset(void *buffer, int c, int count) 

清空数组: memset(buffer, 0, sizeof(buffer))

static成员需要类外初始化

返回值为引用时,不调用复制构造函数

int *a[5]:数组名是a,每个元素为指针类型

int (*a)[5]:数组名是a,每个元素是数组类型

当一个cin对象作为条件选择、循环等的控制表达式时,输入Ctrl+Z可终止循环(cin的返回值依然是cin对象)

闰年二月29天,平年二月28天

lcm(a,b)用于求a和b的最小公倍数

gcd(a,b)用于求a和b的最大公因数

分文件:

模板放在.hpp文件中

cpp中引入该头文件

引用作参数:

1.防止对象所占空间太大而调用复制构造函数

2.可以直接对该对象进行操作

tuplea:三元组,获取第一个int型变量->get<0>(a)

堆栈

C++是编译性语言,编译后生成.exe可执行文件

有:

代码区:只读、共享、存放CPU执行的二进制指令

全局区:存全局变量、静态变量、常量

常量区:存const修饰的常量

栈:存局部变量、形参

堆:存数组、对象

JAVA是解释性语言,编译后生成.class文件,可在多系统(Windows,Mac,Linux等)执行(跨平台)

有:

堆:存数组、对象

栈:局部变量、形参

方法区:常量池(存常量、字符串)、类加载信息

查看运行类型

C++:typeid(对象).name()

JAVA:对象.getclass().simplename() 

关于调试

Clion调试:

F8:下一行       F7:进入函数       F9 :跳转到下一断点      Shift+F8:跳出函数      

VS调试:

F10:下一行     F11:进入函数     Shift+F11:跳出函数       Ctrl+K+F:格式化

关于new和构造

构造函数的初始化列表是专门用来初始化成员对象

Date d与Date * p=new Date没有括号(若有默认为函数声明),有参数时调用构造函数才有括号

注意:new出来的东西要调用delete才会析构,而直接定义的如A a退出main函数时会自动调用析构

Base *pTest2 = new Derived(); //Base类的指针(多态实现:父类指针或引用指向子类对象)

    pTest2->DoSomething();

delete pTest2;

为了防止仅调用Base的析构而不调用Derived的析构造成内存泄漏,故Base类的析构函数要用virtual修饰(构造时先构造Base再构造Derived,析构时先析构Derived,如果new出来的是数组,注意用delete[]全部析构)

注:想要重写一个函数,必须所有东西严格一样,不能多或少一个const或者static

对象数组初始化:{{},{},{},{}~}——{}中的参数调用该类对应的构造函数

自定义二维数组构造器:

Int **p;

Array2(int a, int b) {

        m = a;

        n = b;

        p = new int* [m];

        for (int i = 0; i < m; i++) {

            p[i] = new int[n];

        }

    }

class Person {

public:

       Person operator+(const Person& p) {

              Person temp;

              temp.m_A = this->m_A + p.m_A;

              temp.m_B = this->m_B + p.m_B;//参数对象也可直接访问私有成员

              return temp;

       }

private:

       int m_A;

       int m_B;

};

拷贝构造函数(const A& a)三种调用情况:

  • 用对象初始化另一对象
  • 对象做参数
  • 返回局部变量

Person p2=Person(p1);

Person p3=p1;

Person p4(p1);

Sample a=b调用拷贝构造函数

Sample a;

a=b指向同一对象,地址复制

析构函数只能有一个,不能重载

当指针属性在堆中开辟空间,就自己提供拷贝构造函数,否则系统提供的默认复制构造函数是浅拷贝,会带来重复释放堆区的问题。

浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。

如:String中有char* p,则拷贝构造函数中需要p=new char[strlen(a.p)+1]; strcpy(p,a.p);

自定义二维数组构造器:

Int **p;

Array2(int a, int b) {

        m = a;

        n = b;

        p = new int* [m];

        for (int i = 0; i < m; i++) {

            p[i] = new int[n];

        }

    }

读写文件或数组

文本文件(ASCII码存)

  1. 创建 fstream(读是ifstream,写是ofstream) 对象
  2. 打开文件 open("文件路径",打开方式(in,out,app,binary))
  3. 判断是否打开 is_open()
  4. 写 ofs<<"~"
  5. 读while(ifs>>数组) 读取字符串若有空格或回车则停止,可通过getline(ifs,str)进行读取
  6. 关流 close()

二进制文件(二进制存)

  1. 创建 fstream(读是ifstream,写是ofstream) 对象
  2. 打开文件 open("文件路径",打开方式(in,out,app,binary必选))
  3. 判断是否打开 is_open()
  4. 写 ofs.write((const char*)&a,sizeof(a))--a可以是对象
  5. 读ofs.read((char*)&p,sizeof(p))
  6. 关流 close()

输入输出

cin.get(数组名(char[]),大小,(结束符)): 若无结束语,遇到回车或达到(大小-1)则停止读取。

cin.get():其实就是C语言里的getchar()读取一个字符

cin.getline(数组名(char[]),大小,(结束符)):若无结束语,遇到回车或达到(大小-1)则停止读取。

以上结束符默认为enter,遇到结束符时剩余字符会停留在输入缓冲区(rdbuf),且结束符丢弃

getline(cin/ifs,str):读取每一行(包括空格)并存入str。

cin和cout默认是绑定(若要输入则先要把缓冲区的东西输送到目的地)的,通过cin.tie(0)可以解绑定

ifs/cin>>noskipws:读取char类型时可以读取空格(可以通过skipws恢复)

cin.sync_with_stdio(0):关闭同步,这个时候如果有print又有cout就会先把print的执行完(因为cout会先把数据存到缓冲区,而print直接把数据输出到屏幕)

endl会刷新缓存区,所以为了提升效率用'\n'即可

freopen("文件路径",“r/w”,stdin/stdout):重定向,将cin>>x的键盘输入重定向为文件读入(也可以通过cin.rdbuf(ifs.rdbuf()//文件的缓冲区)将cin的缓冲区挂靠为文件的rdbuf形成重定向)

向一个文件写东西,并且读出并写到另一个文件:

    fstream ofile("file1.txt", ios::in);
    ofstream ofile2("file2.txt", ios::out);
    ofile << "abc\ndef";//写文件
    ofile.seekg(ios::beg);//将指针重新定位文件头
    ofile2 << ofile.rdbuf();//将缓冲区东西输入到第二个文件
    ofile.close();
    ofile2.close();

输出格式化:showpos(正数显示+),showpoint(显示小数点),fixed,scientific,uppercase,left,right,dec,oct,hex等

注:cout.fill()+cout.width()或setw输出方式是对齐

关于重载

   重载[]:

 int*& operator[](int i) {

        return p[i];

    }

重载输出运算符:friend ostream& operator<<(ostream& out, Point& p) {

              out << p.x << "," << p.y;

              return out;

       }

.   ::   ?:   .*   sizeof不可重载

关于模板

普通函数参数为函数时:可以

void fun(int fun2(~)):~依据需求填写,可以不写变量名

void fun(int (*fun2)(~)) 函数体内直接fun2(~)即可,*无影响,当成附加的东西即可

若为模板函数则

Template

Void fun(T fun2){

fun2(~):~依据需求填即可

}

模板中

typename C::const_iterator it(container.begin()):typename用于声明C::const_iterator是类型名而不是一个变量

template

class CMyistream_iterator

{

private:

       T value;

       istream ∈//使用引用的目的是减少开销,避免调用构造函数等等

public:

       CMyistream_iterator(istream &_in):in(_in) {//此处采用引用接受的目的是保证没有复制构造函数调用

              in >> value;//读入第一个数

       }

       T operator *() {

              return this->value;

       }

       void operator++(int) {

              in >> value;//读入后续的数

       }

};

模板实现具体化,前缀+template<>即可

template<> bool myCompare(Person& p1, Person& p2)

{

if (p1.m_Name == p2.m_Name && p1.m_Age == p2.m_Age)

{

        return true;

}

else

{

       return false;

}

}

类型转换

重载强制类型转换:operator int()

{

return n;

}

看某字符的ASCII码:(int)ch;

可以直接给字符赋ASCII码:char ch=97;//int 和 char 可以自动转换

static_cast<类型>(变量):类型转换(类似于C语言里的()

多态中向下转型dynamic_cast (&a)   不要用()直接转

explicit关键字用来防止类构造函数的隐式自动转换

此时

class CxString  // 使用关键字explicit的类声明, 显示转换 

int _size; 

    explicit CxString(int size) 

    { 

        _size = size; 

    } 

}

CxString string2 = 10; CxString string6 = ‘c’;就不行了因为发生不了隐式转换

 关于const

  const Point operator+(const Point &point) const {

              return Point(m_x + point.m_x, m_y + point.m_y);

       }  

  • Point p1 = (10, 20);

       Point p2 = (20, 30);

      (p1 + p2) = Point(40, 50); // 如果不加第1个const,则这里不会报错(应当让常量不能被赋值)

  • Point p1 = (10, 20);

        const Point p2 = (20, 30);

        Point p3 = p1 + p2; // 不加第2个const,这里会报错,因为p2是常数(应当让常量也可以参与运算)

  • const Point p1 = (10, 20);

        Point p2 = (20, 30);

        Point p3 = p1 + p2; // 不加第3个const,这里会报错,因为p1是常数(让常量可以调用函数)

Point& operator++() {} // 默认代表重载++a(a为变量)

const Point operator++(int) {} // 传入参数写int代表a++,固定格式。不能返回局部变量的引用

常量指针:const int* p=&a (常的是*,故指向可以改变,但不能*p=其他东西)

指针常量:int* const p=&a(常的是指针,故指向不可改变,但可以*p=其他东西)

常函数不可更改本类成员变量(除非有mutable修饰)

静态成员变量需要在类外初始化;

静态函数只能调用静态东西

常函数和普通函数啥都能调用

常对象只能调用静态成员函数常成员函数

普通对象和静态对象啥函数都能调用

字符串与int、double转换

#include

atof(字符数组.c_str()):返回该字符串对应的double值,类似于java中的Double.parseDouble(字符串)

atoi(字符数组.c_str()):返回该字符串对应的int值,类似于java中的Integer.parseInt(字符串)

gcvt(double值,8(精度),字符数组):取double值8的精度存到字符数组中,类似于java中的double值+“ ”

itoa(int值,字符数组,10(进制)):取int值以10进制存到字符数组中,类似于java中的int值+“ ”

to_string(int a):int转变为string

访问权限

public

protected

private

公有继承

public

protected

不可见

私有继承

private

private

不可见

保护继承

protected

protected

不可见

子类可以调用本类对象继承来的保护性成员,但不能调用父类对象的该保护成员(只给子类看,其实例对象也不能看)

C++笔记(细节)_第1张图片

Son son

son.Father::m:继承中有同名属性想访问父类的属性时

class Base {
public:
    virtual void fun(double) {
        cout << "base~";
    }
};

class Son : public Base {
public:
    void fun(int) {//也有继承过来的fun,这里是非多态,因为形参不同
        cout << "Son~";
    }
};

int main() {
    Son s;
    s.Base::fun(3.3);//若是s.fun优先调用本类的,调用父类的fun可以像这样显示声明
    return 0;
}

virtual void fun()=0是纯虚函数,使其子类可以重写

当有virtual修饰时,多继承时该类指向同一块区域,不需要限定访问权限(不需要d::B.a,直接d.a),解决二义性。

C++笔记(细节)_第2张图片

C语言独有

getchar()读取一个字符

gets()读取字符串

Char *a=“abc”;

十进制输出:%d

八进制输出:%o

十六进制输出:%x

字符串输出:%s

字符输出:%c

浮点形式输出:%f

C/C++中的strcpy(),strcat(),strlen(),strcmp()都是操控字符数组的

string类

string类初始化:

  • const char* str=”hello”;
  • string str(10,’a’):10个a构成
  • string str=”hello”;
  • string str;

str.assign(“hello”)

  • string str;

str.assign(5,’x’)

string类方法

  • +
  • append
  • find():返回下标
  • rfind():返回最后一个下标
  • replace(1,3,“abc”):将从1始3个字符换成abc
  • compare():若相等返回0
  • size():字符串长度
  • at、[]可访问
  • insert(num,”abc”):在num处插入abc
  • erase(1,3):删除从1始3个字符
  • substr(1,3):从1始截取3个字符

内置数据结构

vector初始化:

  • vectorv2(v1.begin(),v1.end())
  • vectorv(10,100):10个100
  • vectorv3(v1)

v.assign(v2.begin(),v2.end()):给v重定义为v2的对应位置

size实际有的元素个数(resize(n,(m))可以更新元素个数,若只有n,就是n个默认构造的东西,若还有m就是n个m。

capacity是容量,如果size>capacity就会自动扩容(reserve(n)可以手动扩容为n)。

注:

  1. vector对象的大小都是12个字节(两个指针(element、vptr)和int size)
  2. vector重载了==,判断的是内容是否相等

优先队列

struct node {//重写<    
    int val;

    bool operator<(const node& a) const
    {
        return val < a.val; //大顶堆
    }
};
priority_queue<node> myque1;  //类似于Java节点实现Comparable接口内部重写compareTo方法
struct node2 {//谓词

    bool operator()(node a, node b) {
        return a.val < b.val;
    }
};
priority_queue<node, vector, node2> myque2;//内置结构谓词不需(),类似Java中new Comparetor 重写Compare方法

vector

deque

stack

queue

list

set

map

Push_back()

Push_back()

Push_front()

Push()

Push()

Push_front()

Push_back()

Erase()

Clear()

Pop_back()

Pop_back()

Pop_front()

Pop()

Pop()

Clear()

Erase()

Pop_back()

Pop_front()

Remove()

Erase()

Erase()

Clear()

[]、at()

[]、at()

大小

Size()

Size()

Size()

Size()

Size()

Size()

容量

Capacity()

指定大小

Resize()

Resize()

Resize()

插入

Insert()

Insert()

Insert()

(插入后自动排序)

Insert()

(插入后根据值自动排序)

Empty()

Empty()

Empty()

Empty()

Empty()

Empty()

Front()

Front()

Top()

Front()

Front()

Back()

Back()

Back()

Back()

交换

Swap()(自换可收缩容量)

Swap()

Swap()

Swap()

反转

Reverse()

预留空间

Reserve()

迭代器

iterator

iterator

iterator

iterator

Const_iterator

备注

Set不允许重复插入数据,multiset可

Map不允许有重复key,multimap可以

仿函数与谓词

函数对象即仿函数是重载了()的类

若返回的是bool类型,则该仿函数也叫谓词(一个参数就一元谓词,两个参数就二元谓词)

List不可跳跃访问(即不可it=it+1;但可it++)

cout<< a(3, 4) or  A()(3,4);//可以直接通过类对象()调用重载函数

for_each(a.begin(), a.end(), A() or a);//做仿函数不需要写参数,普通函数可以直接写函数名

set,map想要定制排序也可以在设定

仿函数也可以用lambda函数实现,如[](int a,int b){return a>b;}

关于lambda

  1. 如上,用作仿函数
  2. function f=[&(地址传递,可更改外部变量)or=(数值,不可更改or空着)](int a){}       返回类型(传入类型)一般来说auto即可,如果是用到递归就要#include并且写前面这一堆用于说明这个是函数,类似于typename

内建仿函数

  • plus
  • minus
  • multiplies
  • divides
  • modulus:取模
  • negate:取反
  • greater
  • greater_equal
  • less
  • less_equal
  • equal_to
  • not_equal_to
  • logical_and
  • logical_or
  • logical_not

STL算法

遍历

  • for_each(beg,end,fun)
  • transform(beg1,end1,beg2,fun): 搬运容器到另一个容器中

查找

  • find(beg,end,value):返回迭代器
  • find_if(beg,end,fun):按条件找
  • adjacent_find(beg,end):找相邻重复元素的第一个的迭代器
  • binary_search(beg,end,value):找到返回true
  • count(beg,end,value):统计个数
  • count_if(beg,end,fun):根据条件统计个数
  • lower_bound(beg,end,value):用二分查找的方式查找第一个>=value的数的指针
  • upper_bound(beg,end,value):用二分查找的方式查找第一个>value的数的指针

排序

  • sort(beg,end,fun)
  • random_shuffle(beg,end):随机排序
  • merge(beg1,end1,beg2,end2,destination):合并两有序容器中的元素到新容器
  • reverse(beg,end):反转

拷贝、替换

  • copy(beg,end,destination)
  • replace(beg,end.old,new)
  • replace_if(beg,end,fun,new)
  • swap(container1,container2)

算数生成(包含numeric)

  • accumulate(beg,end,value)
  • fill(beg,end,value):填充

集合

  • set_intersection(beg1,end1,beg2,end2,destination):
  1. 两集合元素有序
  2. 目标容器指定大小为min(v1,v
  3. 返回值是交集最后一个元素的迭代器
  • set_union(beg1,end1,beg2,end2,destination)
  1. 两集合元素有序
  2. 目标容器指定大小为size(v1)+size(v
  3. 返回指是并集最后一个元素的迭代器
  • set_difference(beg1,end1,beg2,end2,destination)
  1. 两集合元素有序
  2. 目标容器指定大小为max(v1,v2)
  3. 返回值是差集最后一个元素的迭代器

你可能感兴趣的:(c++,开发语言)