C/C++易错难点笔记02
2015-08-21 17:06
225 查看
C++有很多基础但是,又容易出错的地方,也有很多我们 没有关注的地方,这里慢慢总结积累,记录下来。
下面的做法是错误的:
A.16,val2会被覆盖
B.其他三项都不对
C.8,val2会被覆盖
D.8,val1会被覆盖
解析:1.首先要看编译器,不同的编译器结果可能不一样;
2.sizeof(src),数组名作为形参时,是作为地址来看待的,下标[ ]中的数组是无用的,可以看作是指针,即求指针的大小;
3.一般情况,val1会被覆盖,变量入栈顺序与申明次序相同,栈的地址是从高到低生长的,而数组是从低地址到高地址的,也就是说dst[0]的地址小于dst[1]的地址。所以val1被覆盖。
输出是多少?
A.0,1
B.1,1
C.1,0
D.0,0
解析:首先要注意这是C++中,const变量是编译时的常量,可以像#define定义的常量一样使用。故C++中const变量的值在编译时就已经确定了,直接对const变量进行了值的替换,在汇编阶段,引用到const修饰的量的地方会直接以值替换掉。实际上常量值已经改变了,只不过是被提起替换了而已。还要注意这是局部的const,全局的就不能修改了。
1.C中const是运行时const,编译时只是定义,在运行才会初始化,所以可以通过指针修改const值。这也是为什么不能用const变量作为数组定义的大小的原因。
2.C++中涉及到常量折叠:它指const变量(即常量)值 放在编译器的符号表中 ,计算时编译器直接从表中取值,省去了访问内存的时间,从而达到了优化。
3.const对存放位置没有影响,有影响的是static修饰的变量。
4.const全局变量存储在全局存储空间,其值只有可读属性,不能修改;
const局部变量存储在堆栈中,可通过指针修改其值;
const变量在预处理是处理,编译器只对其值读取一次。
sizeof(a)的值是().
解析:首先,#pragma pack(2) 强制设定为2字节对齐
i 4字节
u 一个为13,该处强制为2字节对齐,实际为13+1=2*7=14字节
color 枚举类型的实例 4字节
4+14+4=22字节
解析:语句3是一个声明,而不是对象初始化。
解析:define在预处理阶段就把main中的a全部替换为10了.
另外,不管是在某个函数内,还是在函数外,define都是从定义开始知道文件结尾,所以如果把foo函数放到main上面的话,则结果会是50 ,50。而#undef a #define a 50,作用域是接下来的代码。
解析:A B D C
之所以是先释放 D 在释放 C的原因是, 程序中首先调用的是 C的构造函数,然后调用的是 D 的构造函数,析构函数的调用与构造函数的调用顺序刚好相反。
p1申请的空间里的值是随机值,p2申请的空间里的值已经初始化为0。
基础知识点
1. 易误解:如果int a[5], 那么a与&a是等价的,因为两者地址相同。
解答:一定要注意a与&a是不一样的,虽然两者地址相同,但意义不一样,&a是整个数组对象的首地址,而a是数组首地址,也就是a[0]的地址,a的类型是int[5],a[0]的类型是int,因此&a+1相当于a的地址值加上sizeof(int) * 5,也就是a[5],下一个对象的地址,已经越界了,而a+1相当于a的地址加上sizeof(int),即a[1]的地址。2. 如何在类中定义常量成员并为其初始化?
解答:只能在初始化列表里对const成员初始化,像下面这样:[code]class CBook { public: const double m_price; CBook() :m_price(8.8) { } };
下面的做法是错误的:
[code]class CBook { public: const double m_price; CBook() { m_price = 8.8; } };
3. 在定义类的成员函数时使用mutable关键字的作用是什么?
解答:当需要在const方法中修改对象的数据成员时,可以在数据成员前使用mutable关键字,防止出现编译出错。例子如下:[code]class CBook { public: mutable double m_price; // 如果不加就会出错 CBook(double price) :m_price(price) { } double getPrice() const; // 定义const方法 }; double CBook::getPrice() const { m_price = 9.8; return m_price; }
4. 在C++中,如果确定了某一个构造函数的创建过程,在该构造函数中如果调用了其它重载的构造函数,它将不会执行其它构造函数的初始化列表部分代码,而是执行函数体代码,此时已经退化成普通函数了。
例子说明如下:[code]class CBook { public: double m_price; CBook() { CBook(8.8); } CBook(double price) : m_price(price) { } }; int main() { CBook c; cout << c.m_price << endl; // 此时并不会输出理想中的8.8 }
易错题
1. 函数栈数组越界覆盖问题
下面程序输出什么:[code]int function(const int src[16]){ int val1=0; int dst[16]={0}; int val2=0; const int *psrc=src; //问题1:如下代码行输出什么? fprintf(stdout,"size of src=%lu\n",sizeof(src)); //问题2:如下代码有什么副作用? for(int i=0;i<=16;i++){ dst[i]=*psrc+i; psrc++; } return 0; }
A.16,val2会被覆盖
B.其他三项都不对
C.8,val2会被覆盖
D.8,val1会被覆盖
解析:1.首先要看编译器,不同的编译器结果可能不一样;
2.sizeof(src),数组名作为形参时,是作为地址来看待的,下标[ ]中的数组是无用的,可以看作是指针,即求指针的大小;
3.一般情况,val1会被覆盖,变量入栈顺序与申明次序相同,栈的地址是从高到低生长的,而数组是从低地址到高地址的,也就是说dst[0]的地址小于dst[1]的地址。所以val1被覆盖。
2. C和C++中const问题
在c++中:[code]const int i = 0; int *j = (int *) &i; *j = 1; printf("%d,%d", i, *j)
输出是多少?
A.0,1
B.1,1
C.1,0
D.0,0
解析:首先要注意这是C++中,const变量是编译时的常量,可以像#define定义的常量一样使用。故C++中const变量的值在编译时就已经确定了,直接对const变量进行了值的替换,在汇编阶段,引用到const修饰的量的地方会直接以值替换掉。实际上常量值已经改变了,只不过是被提起替换了而已。还要注意这是局部的const,全局的就不能修改了。
1.C中const是运行时const,编译时只是定义,在运行才会初始化,所以可以通过指针修改const值。这也是为什么不能用const变量作为数组定义的大小的原因。
2.C++中涉及到常量折叠:它指const变量(即常量)值 放在编译器的符号表中 ,计算时编译器直接从表中取值,省去了访问内存的时间,从而达到了优化。
3.const对存放位置没有影响,有影响的是static修饰的变量。
4.const全局变量存储在全局存储空间,其值只有可读属性,不能修改;
const局部变量存储在堆栈中,可通过指针修改其值;
const变量在预处理是处理,编译器只对其值读取一次。
3. 枚举和联合在类中占用的内存问题
在32位机器上,下列代码中sizeof(a)的值是().
解析:首先,#pragma pack(2) 强制设定为2字节对齐
i 4字节
u 一个为13,该处强制为2字节对齐,实际为13+1=2*7=14字节
color 枚举类型的实例 4字节
4+14+4=22字节
4. 默认构造和函数声明问题
下列代码编译时会产生错误的是()解析:语句3是一个声明,而不是对象初始化。
5. define问题
以下代码的输出结果是?[code] #define a 10 void foo(); main(){ printf("%d..",a); foo(); printf("%d",a); } void foo(){ #undef a #define a 50 }
解析:define在预处理阶段就把main中的a全部替换为10了.
另外,不管是在某个函数内,还是在函数外,define都是从定义开始知道文件结尾,所以如果把foo函数放到main上面的话,则结果会是50 ,50。而#undef a #define a 50,作用域是接下来的代码。
6. 局部静态对象和全局对象析构顺序
设已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为?[code]C c; void main() { A*pa=new A(); B b; static D d; delete pa; }
解析:A B D C
之所以是先释放 D 在释放 C的原因是, 程序中首先调用的是 C的构造函数,然后调用的是 D 的构造函数,析构函数的调用与构造函数的调用顺序刚好相反。
7. 内置变量初始化问题
下面描述正确的是[code]int *p1 = new int[10]; int *p2 = new int[10]();
p1申请的空间里的值是随机值,p2申请的空间里的值已经初始化为0。
相关文章推荐
- C++ new 之 placement new、operator new、new operator
- c++ 四大函数练习
- (1.1.29)C++中定义类的对象:用new和不用new有何区别?
- C++静态成员函数小结
- 第一日学习(一)osgViewer/ViewerBase.cpp
- C++栈的实现
- C语言i++和++i的区别和指针*(a++)和*(++a)的区别
- C++对象模型
- c++对象内存模型【内存布局】
- Effective C++学习笔记五(实现)
- Performance Log
- 【转】笔试常考:C语言字节对齐
- [黑马程序员]C语言结构体
- C++中的set_new_handler和new_handler 【未完待续】
- C++字符串转数字,数字转字符串
- java语言和C/C++语言的关系
- Z字形扫描
- C++11 右值引用与move语义
- C语言的static和extern关键字的使用
- C/C++编程题之计算一个数字的立方根