C++编程中常遇到的问题

1、路径中不能存在空格

2、for等循环结构中,如果判断条件的变量是size_t或者unsigned时,最好不要采用“--i”来递减变量,因为这两种类型没有负数。

3、引用的引用不可用: int& &i ;(不合法,且注意两个&之间有空格,否则就会被声明为右值引用)。

4、int *p[10] ; sizeof(p) 是指数组所占的长度,虽然p本身是一个指针。

5、if判断语句中,当要配合else使用时,最好不要在条件语句中同时存在多个判断语句。

6、因为引用本身并非对象,所以不存在指向引用的指针: int& *ptr;(不合法)。

7、字面值常量字符串 ”aaa“的经过sizeof函数后计算的空间是4,在其最后存在一个空字符。

8、在执行读取操作时,string对象会自动忽略开头的空白并从第一个真正的字符开始直至遇到下一个空白。

9、对于一个复杂类型的变量声明(eg: int *&r),以变量名为中心,从右到左分析。如果有括号那么先括号内然后遇括号跳出括号继续从右到左分析。

10、常量表达式是值不会改变且在编译过程中就能得知结果的表达式,数组的维度必须是一个常量表达式。

11、指针也是迭代器,指针相减的结果类型是ptrdiff_t。

12、标准库类型(string、vector)的下标索引必须是无符号类型,而内置的下标运算无此要求即可以是负数,如内置数组,只要arr[-2]等价于*(arr-2)指向的元素还在数组内就ok。

13、char *p = "abc", char p[] = "abc"; 这两个p虽然都是都是指针,但不一样。前者只想的是一个字符串字面量,开辟的存放空间在常量区,所以不能用指针去修改其值。而后者不存在这样的问题。

14、关于后置递增运算符(i++),在语句中使用前,先求值产生一个等于原值的右值副本temp_i,然后将这个副本应用于这条语句中。执行完该语句后 i 在自加1。

15、C\C++中,当给cout一个字符指针的时候,它就一直输出,直到遇到 ‘\0’ 这个结尾,如果不存在‘\0’ 则会发生输出错误。

16、int a[10]{}; *(a+1)是a中的第一个元素,*(&a+1)指向的下一个类型int(*)[10]的数组。

17、memset是以字节为单位,初始化内存块。void *memset(void *s, int ch, size_t n);将s中前n个字节 (typedef unsigned int size_t )用ch替换并返回s.

18、无符号数与有符号数相比较,会将有符号书转化为无符号数,负数会变成一个很大的无符号数。

19、二维数组定义中,行可以省略,列不能。

20、程序占用三种类型的内存:静态内存、栈内存、堆内存; 
静态内存: 
用来保存局部static对象、类static数据成员以及定义在任何函数之外的变量 
栈内存: 
用来保存定义在函数内的非static对象。分配在静态内存或栈内存中的对象由编译器自动创建和销毁。对于栈对象,仅在其定义的程序块运行时才存在;static对象在使用之前分配,在程序结束时销毁。
堆内存: 
在程序运行时分配。动态对象的生存周期由程序(用户)来控制。

21、深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同)。对其中任何一个对象的改动都会影响另外一个对象。

22、const int* const a = &b;等价于 int const* const a = &b;

23、传引用、传指针最终传的都是地址。

24、回调函数就是一个通过函数指针调用的函数。

25、使用volatile关键字声明的变量,系统总是重新从它所在的内存中读取数据,即使它前面的指令刚刚从该处读取过数据,而且读取的数据立刻被保存;相反,若没有使用volatile,编译器可能会做优化处理,可能暂时使用寄存器中的值,而如果该变量由别的程序更新了的话,将会出现不一致的现象!

26、面向对象的五个基本原则: 

单一职责原则(Single-Resposibility Principle):一个类,最好只做一件事,只有一个引起它的变化。单一职责原则可以看做是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。
开放封闭原则(Open-Closed principle):软件实体应该是可扩展的,而不可修改的。也就是,对扩展开放,对修改封闭的。
Liskov替换原则(Liskov-Substituion Principle):子类必须能够替换其基类。这一思想体现为对继承机制的约束规范,只有子类能够替换基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基础。
依赖倒置原则(Dependecy-Inversion Principle):依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。
接口隔离原则(Interface-Segregation Principle):使用多个小的专门的接口,而不要使用一个大的总接口

27、构造函数不能声明为虚函数的原因是: 

1 )构造一个对象的时候,必须知道对象的实际类型,而虚函数行为是在运行期间确定实际类型的。而在构造一个对象时,由于对象还未构造成功。编译器无法知道对象 的实际类型,是该类本身,还是该类的一个派生类,或是更深层次的派生类。无法确定。
2) 虚函数的执行依赖于虚函数表。而虚函数表在构造函数中进行初始化工作,即初始化vptr,让他指向正确的虚函数表。而在构造对象期间,虚函数表还没有被初 始化,将无法进行。虚函数的意思就是开启动态绑定,程序会根据对象的动态类型来选择要调用的方法。然而在构造函数运行的时候,这个对象的动态类型还不完整,没有办法确定它到底是什么类型,故构造函数不能动态绑定。(动态绑定是根据对象的动态类型而不是函数名,在调用构造函数之前,这个对象根本就不存在,它怎么动态绑定?)
编译器在调用基类的构造函数的时候并不知道你要构造的是一个基类的对象还是一个派生类的对象。

28、非常量引用定义时,其初始化的对象必须为左值!(int &a = 3;非法)

29、大小端:小端中低地址低字节,高地址高字节;大端相反。80X86是小端模式。

30、 派生类的构造函数执行过程,析构函数的执行过程一般与构造函数执行的过程相反。

       1)、创建派生类的对象,基类的构造函数函数优先被调用(也优先于派生类里的成员类);
  2)、如果类里面有成员类,成员类的构造函数优先被调用;
  3)、基类构造函数如果有多个基类则构造函数的调用顺序是某类在类派生表中出现的顺序而不是它们在成员初始化表中的顺序;
  4)、成员类对象构造函数如果有多个成员类对象则构造函数的调用顺序是对象在类中被声明的顺序而不是它们出现在成员初始化表中的顺序;
  5)、派生类构造函数
  作为一般规则派生类构造函数应该不能直接向一个基类数据成员赋值而是把值传递给适当的基类构造函数否则两个类的实现变成紧耦合的(tightly coupled)将更加难于正确地修改或扩展基类的实现。(基类设计者的责任是提供一组适当的基类构造函数)。

31、 函数的退出通常有两种情况,正常退出和异常退出,无论是什么情况下的退出,局部对象都会被销毁。但通过new开辟的内存空间,在对应的delete之前发生了异常是不会释放该空间的。因此推荐使用智能指针,总是能正确的释放内存。

32、符号不明确:可能是因为定义的符号与命名空间中的某些符号相同,换一个符号可能就行。

33、类型不完整,可能是由于未包含相关的头文件。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:设计师小姐姐 返回首页