C++笔记

signedunsigned的转换:

①无符号转有符号:若是最高位为0,说明无符号没有超过有符号的范围,那么有符号数直接等于无符号数,若是无符号的最高位为1,那么将非符号位取补码,得到的数就是有符号位。

②有符号位转无符号位:若是最高位为0,说明有符号数为整数,那么无符号数就是有符号数,若是有符号数的最高位为1,那么将符号位取补码得到无符号数。

比如说对于

unsigned char uschar=233;

signed char schar=uschar;//那么schar=233-256=-23;

//

signed char schar=-23;

unsigned char uschar=schar;//那么schar=-23+256=223;

超过了就减,是负数就加

#define和typedef:(P61)

①  #define只是简单的宏替换

②  typedef则是声明一种新的类型

③  举个简单的例子。

#define int * p_int;

typedef int * P_INT;

const p_int ptr1;

const P_INT ptr2;

由于ptr1是简单的宏替换,所以ptr1一个指向常量的指针,其值不可以改变;

ptr2则是一个常量指针,其指向的对象不可以发生变化。

C++11 新标准auto(P61),自动推断变量类型,如auto n=10;

C++11新标准decltype(P62),根据表达式推断变量类型,如decltype(f()) sum=x;decltype(a) b=0;

string str1=”nihaoa”  //拷贝初始化P(76)

stirng str2(“nihaoa”); //直接初始化

string连续加法:

对于string的连续加法而言,+两侧必须有一个为string对象,如

string str=”rrr”+”oooo”;//编译不会通过,因为”rrr”和”oooo”为char *类型,string加法用的是+运算符的重载。应该注意的是”rrr”是C语言中的char *写法,而string则是C++中标准库中的一个类型。

数组在函数参数传递的时候退化为指针,在取地址符(&)、sizeof和typeid等运算符的运算对象时,转换则不会发生。P143

C++显示转换,强制转换分为四种:

static_cast,使用static_cast转换的转换结果和原始的地址相等,因此必须确保转换后所得的结果的正确性,如将int *转换为double*则会产生未定义的结果。

void *p=&d;

Int *a=static_cast<int *>p;

dynamic_cast,

const_cast,将常量对象转换为非常量对象。如:

const int a=10;

int &b=const_cast<int&>(a);

b=99;

reinterpret_cast

在C++中,char* 等于const char *,如char *str=”yyy”;存储在常量区,所以不能通过str来改变str。char str[]=”yyy”;存储在栈中。

C++ 内存分布:

常量区,如char *str=”2222”;

静态区,存储static和全局变量

代码区

函数指针:在代码区中,函数名代表函数的首地址。如有函数int Add(int a,int b);

typedef int (*ptr_func)(int ,int) //声明一个函数指针

ptr_func Add_func=Add;//令Add_func指向Add

int a=Add_func(1,2); //调用Add

static作用:

1、  规定作用域,使用范围只能在本文本内

2、  规定存储方式,存储在静态区

const作用:变量不能修改

C++默认初始化:

1、  任何定义在函数体外的变量调用默认构造函数,内置类型和组合类型没有构造函数,那么则初始化为0;

2、  定义在函数体内的对象默认初始化为未定义的;

3、  对于类类型内的变量,与1相同,如果变量存在默认构造函数,则调用默认构造函数,否则被默认为0

值得注意的是,对于new的动态分配的对象是默认初始化的,这意味着内置对象或者组合类型的对象的值是未定义的,而类类型的对象将用默认构造函数进行初始化。

Int *i=new int;//i是未定义的

int * i=new int();//i=0

string *str=new string(9,’c’);

类的静态成员:

java在第一次使用类的时候会初始化类的静态成员,这发生在类的初始化之前。但是在C++中,并不是在类第一次使用前初始化这些静态成员的。一般而言,我们不能在类的内部初始化静态成员。相反地,必须在类的外部定义和初始化每个静态成员。和其他对象一样,一个静态数据成员只能定义一次,和全局变量一样,静态数据成员定义在任何函数之外,因为一旦它被定义,就将一直存在于整个程序的生命周期里。如:P270

class Base

{

public:

static int age;//不能这样定义:staticint age=19;不能在类的内部初始类的静态变量

}

在main函数中定义:int Base::age=19;//错误,不能在任何函数内部初始化定义类的静态变量。

静态变量的调用:Base base;base.age;或者是Base::age

局部静态变量只会被定义一次,当再次进入函数区域时候,此时局部静态变量已经被定义过了,所以可以直接使用这个局部静态变量:如:

void getstatic()

{

Static int aa=100;//第二次进入函数时不会执行这条语句,会直接执行aa++

aa++;

}

Class和struct的唯一区别是默认的访问权限不同,class默认是private,struct默认则是public

explicit关键字:用于阻止类类型之间的隐形转换,如:

class Person

{

public:

 explicit Person(const char *);

}

那么Person p=”mcfer”;则会报错,如果没有explicit则可以这样写。

Class Person

{

Public:

 Person(string name);

}

那么Person p=”mcfer”;则会报错,因为这里发生了两次隐式转换,一次是const char*转为string,然后将string转为Person。

我们比较常用的是string(const char*)不是explicit;vector<T>(int length)则是explicit的。

与其他顺序容器不同的是,swap两个array会真正交换他们的元素,因此,交换两个array所需的时间与array中元素的数目成正比,这导致array在进行swap交换操作之后,指针、引用、迭代器都不会失效,但是元素值已经与另外一个array中对应的元素值进行了交换。对于其他顺序容器而言,指向容器的迭代器、引用和指针都不会失效。P303

注意,在移动操作及拷贝移动和赋值移动都不是默认合成的。

一般而言,析构函数被定义成virtual的,不然的话没法释放子类部分的内存。

问题:当两个string对象同时指向了一个constchar*,那么调用string的析构函数会发生什么呢?因为string有移动复制构造函数,那么:

String str1=”aaa”;

String str2=std::move(str1);

那么当str1析构后,str2还能够使用,其内部是怎么实现的呢?

Struct和class的唯一区别是默认的成员访问权限和派生类访问说明权限,其中struct为pubic,class为private。

抽象基类:在类的方法中存在=0这样的声明,这说明类是抽象类,不能被实例化。如:

Class Person

{

Void Getage() const & =0//这里用了三种限定符,即const、&和=0

}

派生类覆盖重载函数:

成员函数无论是否是虚函数都能被重载。派生类可以覆盖重载函数的0个或者是多个版本,但是如果派生类希望所有的重载版本都是可见的,那么派生类就需要覆盖父类的所有版本或者是0个版本。如:P551

Class Base

{

Public:

Void sayhello();

}

Class Child1:public Base

{

Public:

Void sayhello(std::string str);

}

此时调用Child.sayhello()会报错,因为找不到sayhello()的版本,子类如果想继承父类的重载版本,那么子类要么重载所有的重载函数,要么一个都不重载,即子类中不重载sayhello(string)版本的话,父类中的sayhello()是可以用的。如果不想重载的话,可以在子类中写using Base::syahello;

当派生类中定义了拷贝构造函数、移动构造函数和赋值操作时,该操作需要负责拷贝、移动和赋值包含基类部分成员在内的整个对象。和构造函数一样,如果我们想拷贝、移动和赋值派生类的基类部分,需要在派生类的这些操作中显式的调用基类的这些函数。否则拷贝函数和移动函数会调用父类的默认构造函数进行基类构造,赋值函数则不会对父类进行赋值,其值是未定义的。

class Base

{

public:

Base(string str);//构造函数

Base(Base&);//赋值构造函数

Base(Base &&);//移动构造函数

Base & operator=(constBase&);//赋值函数

Base& operator(Base&&);//移动赋值函数

virtual ~Base();//析构函数

}

class Child

{

public:

Child(string str):Base(str){};

Child(Child& child):Base(child){};

Child(Child&&child):Base(std::move(child)){};

Child& operator=(Child &child){Base::operator=(child);};

Child&operator=(Child&& child){Base::operator=(std::move(child))};

~Child(){}//自动调用Base的析构函数

 }

构造函数(没有默认构造函数):

delete和析构函数不是一回事。delete在调用析构函数后会释放掉new创建的内存空间,而如果仅仅是调用析构函数的话,此时就是一个普通的函数,要看析构函数怎么写了。如:

class Mystring

{

public:

int age;

char *c;

Mystring()

{

c=new char[10];

strcpy(c,”aaaa”);

}

~Mystring()

{

delete []c;

}

}

Mystring *ms=new Mystring();

ms->~Mystring();//调用析构函数,此时只会执行析构函数里的内容,但是Mystring的内存还是没有释放,这里包含有存在堆中的一个指针和一个int

delete ms//这里会调用析构函数,同时释放掉ms的空间,ms变成未定义的。

new、operator new、placementnew区别:

new opeartor和delete operator就是new和delete操作符,而operatornew和operator delete是函数。

new operator://用于分配内存空间和调用构造函数

(1)    调用operator new函数进行内存的分配,并调用相关对象的构造函数;

(2)    不可以被重载

operator new://用于分配内存空间operatornew(size_t)

(1)    只分配所需要的空间,不调用相关对象的构造函数,当无法满足所需分配的空间时,如果有new_handler,则调用new_handler。

(2)    可以被重载

(3)    重载时,返回类型必须是void *

(4)    重载时,第一个参数必须是要分配空间的大小,类型为size_t

(5)    重载时,可以带其他参数

Placement new://用于调用构造函数

(1)    用法,如:

Person *p=(Person*)(operator new(sizeof(Person)));

new(p)Person(10,”mcfer”);//在p的位置上调用Person的构造函数构造对象。

也可以这样用:

Person *p=new Person(20,”mcfer”);

new(p)Person(99,”uuuu”);//没有调用person的析构函数

new 、operator new 和 placementnew 区别

(1)new :不能被重载,其行为总是一致的。它先调用operator new分配内存,然后调用构造函数初始化那段内存。

new 操作符的执行过程:

1. 调用operator new分配内存 ;

2. 调用构造函数生成类对象;

3. 返回相应指针。

(2)operator new:要实现不同的内存分配行为,应该重载operator new,而不是new。

operator new就像operator + 一样,是可以重载的。如果类中没有重载operator new,那么调用的就是全局的::operator new来完成堆的分配。同理,operator new[]、operator delete、operator delete[]也是可以重载的。

(3)placement new:只是operator new重载的一个版本。它并不分配内存,只是返回指向已经分配好的某段内存的一个指针。因此不能删除它,但需要调用对象的析构函数。

如果你想在已经分配的内存中创建一个对象,使用new时行不通的。也就是说placement new允许你在一个已经分配好的内存中(栈或者堆中)构造一个新的对象。原型中void* p实际上就是指向一个已经分配好的内存缓冲区的的首地址。

 

C++编译与连接:

在c++中,每个cpp文件都是单独编译的。在编译的过程中,每个编译之后的文件都会导出一个导出符号表、未解决符号表和地址重定向表,其中导出符号表里包含这个目标文件导出的一些变量和函数,未解决符号表表示这个目标文件里没有找这些符号的定义,可能有声明。需要链接其他的目标文件查找符号。地址重定向表是符号的重定向信息。链接分为外链接和内链接,外链接表示其他的目标文件可以使用这个目标文件里的外链接变量或者函数。如果在文件中声明了static或者const,则表示这个变量或者函数是属于内链接,不通过导出符号表导出。值得注意的是并没有extern static这种写法,但是存在着extern const,这表示const是外;连接变量。

在头文件中定义了const符号?如果这个头文件被多个cpp包含,则表示这个const符号有多个定义,但是程序并不会报错,编译之后导出的符号表中的符号并没有冲突。但是这导致的后果就是在每个cpp中取得这个符号的地址不一致,如果这个符号是mutable,那么修改这个变量则不会导致其他的目标文件中的值发生变化。

为什么class中不能给static或者const直接赋值。因为static和const表示这个符号是内链接,如果这个class.h被多个文件包含的话,那么修改则会无效。

 

C++中的四种转换:

(1). static_cast<>(),c语言中强制转换的替代品。用于基本类型的转换或者是类型之间的转换,但是类型之间的转换必须是有联系的,且这种转换是不安全的。

(2). dynamic_cast<>(),用于基类和派生类之间的转换。只能用于指针和引用转换,其中,必须存在虚函数,否则编译不会通过。若是转换失败,则返回NULL,这种转换是类型安全的。

(3). const_cast<>(),用于将const去除。返回一个非const变量。只能用于指针和引用转换。

(4). reinterpret_cast<>(),通常为操作数的位模式提供较低层的重新解释。比如讲int转换为指针,或者将指针转换为int,一个明显的现象就是转换前后没有数位损失,所以将int转换为double用这种转换就行不通。这种转换仅仅是复制比特位。


 

 

 


 

1、资源项目源码均已通过严格测试验证,保证能够正常运行;、 2项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行;、 2项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 、 1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READmE.文件(md如有),本项目仅用作交流学习参考,请切勿用于商业用途。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值