[整理自用]c++错题(长期更新)
2018-03-06 16:44
197 查看
内存占用空间
题目:若char是一字节,int是4字节,指针类型是4字节,代码如下:class CTest { public: CTest():m_chData(‘\0’),m_nData(0){ }; virtual void mem_fun(){}; private: char m_chData; int m_nData; static char s_chData; }; char CTest::s_chData=’\0’;//静态成员一般不可以在类内初始化,但是const的可以。
问题:
(1)若按4字节对齐sizeof(CTest)的值是多少? 12
(2)若按1字节对齐sizeof(CTest)的值是多少? 9
分析:
1 先找有没有virtual 有的话就要建立虚函数表,+4
2 static的成员变量属于类域,不算入对象中 +0
3 神马成员都没有的类,或者只有成员函数 +1
4 对齐法则(少的算多的)
其他:
1.sizeof的本质是得到某个类型的大小,即创建这个类型的一个对象(或变量)的时候,需要为它分配的空间的大小。
2.static成员变量是存储在静态区当中,是一个共享的量。因此,创建实例对象时,无需再为static成员变量分配空间。
综上,sizeof计算类的大小的时候会忽略static成员变量的大小。
显式调用重载的运算符函数
题目:已知表达式++a中的”++”是作为成员函数重载的运算符,则与++a等效的运算符函数调用形式为:a.operator++();
要点分析:
当重载运算符是成员函数时,this绑定到左侧运算对象。成员运算符函数显式参数数目比运算对象数目少一个。(C5 P490)
递增(递减)运算符显式调用(C5 P504)
前置版本:
a.operator++();
后置版本:
a.operator++(0);
格式化输出
题目:以下程序的运行结果是()int main(void) { printf("%s , % 5.3s\n","computer","computer"); return 0; }
要点分析:
1. %m.ns 表示输出占m列,但只取字符串中左端n个字符。这n个字符输出在m列的右侧,左补空格。
2. 格式化输出如果规定了输出列的,不够的时候是右对齐,左侧补零。够了就全部输出。
4000
答案:
computer,com
题目:假设在一个 32 位 little endian (小端模式) 的机器上运行下面的程序,结果是多少? ( 1,0,2)
#include <stdio.h> int main() { long long a = 1, b = 2, c = 3; printf("%d %d %d\n", a, b, c); return 0; }
要点分析:
long在32位机器是4字节,在64位机器是8字节,但是long long,不管在哪个机器都是8字节;(后续再博客里会整理的)
printf函数的原型是printf(const char*,…);
printf函数是自右向左一股脑压入栈的;
%d输出的是4个字节,int类型所占的字节数。
有了上述四条,本题目就相对比较简单了。由于
a,b,c是
long long类型,占8个字节,因此:
不知道算什么
问题: math.h的abs返回值( )?要点分析:
c中的函数申明为 int abs(int num);
int取值范围是负数比正数多1的,因此:
1. num为0或正数时,函数返回num值;
2. 当num为负数且不是最小的负数时,函数返回num的对应绝对值数,即将内存中该二进制位的符号位取反,并把后面数值位取反加一;
3. 当num为最小的负数时,由于正数里int类型表示不了这个数的绝对值,所以依然返回该负数。
函数调用约定
详细内容见其他人的博客带你玩转Visual Studio——调用约定__cdecl、__stdcall和__fastcall这里仅仅只是拿过来做整理之用。
要点 | __cdecl | __stdcall | __fastcall |
---|---|---|---|
参数传递方式 | 右->左 | 右->左 | 左边开始的两个不大于4字节(DWORD)的参数分别放在ECX和EDX寄存器,其余的参数自右向左压栈传送 |
清理栈方法 | 调用者清理 | 被调用函数清理 | 被调用函数清理 |
适用场合 | C/C++、MFC的默认方式; 可变参数的时候使用; | Win API | 要求速度快 |
C编译修饰约定 | _functionname | _functionname@number | @functionname@number |
优先级
题目:设有定义语句int x[6]={2,4,6,8,5,7}; int *p=x; int i=0;
要求依次输出x数组6个元素中的值,能完成此操作的语句是:
for(i=0;i<6;i++) printf("%2d",*(p++));
分析:
尽管()是最高优先级,但是仅仅只是优先将()内的符号进行结合,而不表示一定先对()内进行计算。所以尽管有括号(),但由于
*和
++优先级相同,而且是右结合,所以事实上
*(p++)等同于
*p++。
题目:设x、y、t均为int型变量,则执行语句后,变量t和y的值分别为__。
t=3; x=y=2; t=x++||++y;
分析:
1.
||运算符与
|。前者是判断表达式最后的结果是真是假,所以只可能是0/1。我开始都没在题目答案中找到 t=1t=1这个答案,这也是答错的重要原因。
2. 运算优先级,赋值运算优先级是很低的。
3.
||,只要前一个表达式为真,则后面一个表达式不做运算了;不然才会继续进行后面表达式的计算。同理
&&,若前一个表达为假,则不会继续对后面的表达式进行计算了。
答案: t=1,y=2t=1,y=2.
时间复杂度
题目:在一台主流配置的PC机上,调用f(35)所需的时间大概是__。(几分钟)
int f(int x) { int s=0; while(x-- >0) s+=f(x); return max(s,1); }
这道题实质上是考时间复杂度的。由于递归是在循环里的,所以其时间复杂度:
O(f(35))=O(f(34))+O(f(33))+…+O(f(0))=235235O(f(0))。现在的计算机大致每秒运算一亿次。所以大约花去235235/100000000m大致为344秒也就是几分钟。
malloc and free
c/c++ new与malloc的区别及使用时注意的问题malloc 函数详解
其他:
malloc 和 free:是管理虚拟内存;所以当然可以通过malloc(size_t)函数调用申请超过该机器物理内存大小的内存块。
同理,无法通过内存释放函数free(void*)直接将某块已经使用完的物理内存直接还给操作系统。(此外,可能是程序结束才还给操作系统)。
结构体
题目:以下定义错误的是:a)a) struct A{A _a;}; b) struct A{A * _a;}; c) struct A{A & _a;}; d) struct B; struct A{B & _b;}; struct B{A & _a;};
题目要点分析:
1. 结构体在完成定义之前是incomplete type(不完全类型),不完全类型不能定义对象,只能定义引用和指针,或者用于声明函数的形参和返回值类型。
2. struct成员类型不可以是它自己。
否则会导致递归定义。 理论上这样导致结构体的大小不能被计算(无限大小)。
但是成员可以定义为该结构体的指针(引用在c++底层是用指针实现的,所以也可以),因为指针的大小是已知的。
纯虚函数与抽象基类
以下内容取自《c++ premier第五版》P540-542页。将虚函数声明语句分号之前书写=0就可以将虚函数定义为纯虚函数。
上述=0 只能出现在类内部的虚函数声明语句处。
含有(或未经覆盖直接继承)的纯虚函数的类是抽象基类。且我们不能直接为抽象基类创建对象。
派生类必须覆盖纯虚函数给出自己的定义,否则它们仍然是抽象基类。
派生类的构造函数只能初始化其直接基类。仍然需要调用抽象基类自己的构造函数来初始化其成员。
纯虚函数可以有函数体,但是定义必须在类的外部。
虚函数可以是另一个类的友元函数,但不能是静态成员函数:
友元函数不能是虚函数,因为友元函数不可以继承.
在基类中声明了虚函数,在派生类中如果不声明,则默认为虚函数。(因此,不一定在派生类中显示声明。)
组合和继承
c++继承和组合的区别总结:
1. 组合也叫“对象持有”,就是在类中定义另一类型的成员。组合拥有良好的扩展性,支持动态组合,因此请优先考虑组合方法;
2. 继承会破坏类的独立性,增加系统的复杂性,一般系统的继承层次不超过3层。
组合和继承优缺点:
组 合 关 系 | 继 承 关 系 |
---|---|
优点:不破坏封装,整体类与局部类之间松耦合,彼此相对独立 | 缺点:破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性 |
优点:具有较好的可扩展性 | 缺点:支持扩展,但是往往以增加系统结构的复杂度为代价 |
优点:支持动态组合。在运行时,整体对象可以选择不同类型的局部对象 | 缺点:不支持动态继承。在运行时,子类无法选择不同的父类 |
优点:整体类可以对局部类进行包装,封装局部类的接口,提供新的接口 | 缺点:子类不能改变父类的接口,但子类可以覆盖父类的接口 |
缺点:整体类不能自动获得和局部类同样的接口 | 优点:子类能自动继承父类的接口 |
缺点:创建整体类的对象时,需要创建所有局部类的对象 | 优点:创建子类的对象时,无须创建父类的对象 |
异常处理
题目:下列关于异常处理的描述中,理解不正确的是:1. C++语言的异常处理机制通过3个保留字throw、try和catch实现。
2. 任何需要检测的语句必须在try语句块中执行,并由throw语句抛出异常。
3. throw语句抛出异常后,catch利用数据类型匹配进行异常捕获。
4. 一旦catch捕获异常,不能将异常用throw语句再次抛出。(错误)
catch异常后,同样可以用throw语句在此抛出,如果没有解决,会直接向上层继续抛,直至main函数,然后异常停止!
相关文章推荐
- C++错误笔记(长期更新)
- ElasticSearch常用分析命令整理(长期更新...)
- 【★更新★】整理发布本人所有博文中提供的代码与工具(C++)
- 【★更新★】整理发布本人所有博文中提供的代码与工具(C++)
- 【★更新★】整理发布本人所有博文中提供的代码与工具(C++)
- IFE-2016SP(百度前端技术学院)代码整理(长期更新)
- 【整理自用】统计学习、机器学习常见算法(整理更新)
- C++中常见错误整理(不定期更新)
- c++学习笔记序列之错误码整理(不断更新中)
- C/C++文档注释神器——Doxygen常用知识整理(持续更新)
- 关于SVM的那点破事[faruto长期更新整理]
- C/C++文档注释神器——Doxygen常用知识整理(持续更新)
- C++实现大正整数及其相关运算(长期更新)
- C/C++零碎知识点整理(不断更新)
- 牛客网C++知识点整理(持续更新)
- 正则表达式收集整理备忘(长期更新)
- 【牛客】2017-10-10 C++错题整理
- 笔试面试中C/C++重要知识点整理(不定期更新)
- C++所学的相关知识点整理(不定期更新)
- 关于SVM的那点破事[faruto长期更新整理]