C++小题(三)

//冯诺依曼体系的五部分是什么?
//冯诺依曼理论的要点是:数字计算机的数制采用二进制;计算机应该按照程序顺序执行。 
//其主要内容是:
//1.计算机由控制器、运算器、存储器、输入设备、输出设备五大部分组成。
//2.程序和数据以二进制代码形式不加区别地存放在存储器中,存放位置由地址确定。
//3.控制器根据存放在存储器中地指令序列(程序)进行工作,并由一个程序计数器控制指令地执行。
//控制器具有判断能力,能根据计算结果选择不同的工作流程。

//
/*
#include<iostream>
using namespace std;
class A
{
    public:
        A()
        {
            printf("0");
        }
        A(int a)
        {
            printf("1");
        }
        A& operator=(const A& a)
        {
            printf("2");
            return*this;
        }
};
int main()
{
    A al;//调用构造函数A()
    al=10;//10转成A对象,调用A(int)构造函数,然后调用赋值构造函数。
}
//012
*/

//

/*关于虚函数的描述正确的是()
正确答案: B   

A派生类的虚函数与基类的虚函数具有不同的参数个数和类型
B内联函数不能是虚函数
C派生类必须重新定义基类的虚函数
D虚函数可以是一个static型的函数*/

//
/*
#include <iostream>
using namespace std;
class A {
public:
    int b;
    char c;
    virtual void print() {
        cout << "this is father’s fuction! " << endl;
    }
};
class B: A {
public:
    virtual void print() {
        cout << "this is children’s fuction! " << endl;
    }
};
int main(int argc, char * argv[]) {
    cout << sizeof(A) << "" << sizeof(B) << endl;//12 12
    return 0;
}
//类的大小只与成员变量(非static数据成员变量)和虚函数指针有关,还要考虑到对齐.
//那么类A的大小等于4个字节 + 4个字节(考虑对齐) + 4个字节(指向虚函数的指针)=12字节;
//类B的大小就是等于类A的大小12个字节.
//因为在基类中存在虚函数时,派生类会继承基类的虚函数,因此派生类中不再增加虚函数的存储空间
//(因为所有的虚函数共享一块内存区域),而仅仅需要考虑派生类中添加进来的非static数据成员的内存空间大小。
//所以类B大小为12
*/
//

//free(ptr)
//如果ptr为NULL,则不会做任何操作
//如果ptr未定义,则会崩溃。

//
//malloc函数进行内存分配是在什么阶段?  选执行阶段 ,malloc 在堆上动态分配内存,在运行时期
//编译阶段
//链接阶段
//装载阶段
//执行阶段


//
/*
Which of the following statements are true?
正确答案: A C D   

A We can create a binary tree from given inorder and preorder traversal sequences.
B We can create a binary tree from given preorder and postorder traversal sequences.
C For an almost sorted array, insertion sort can be more effective than Quicksort.
D Suppose T(n) is the runtime of resolving a problem with n elements, T(n) = Θ(1) if n = 1; T(n) = 2T(n/2) + Θ(n) if > 1; so T(n) is Θ(n log n).
  None of the above.
  //必须要有中序才能得到一颗二叉树的正确顺序
*/ 
//

/*
请说出const与#define 相比,有何优点 ?
BC
A 宏常量有数据类型,而const常量没有数据类型
B 有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试
C 编译器可以对const进行类型安全检查。而对#define只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
*/
//
/*
#include<iostream>
using namespace std;
struct A{ 
char a[10];
int b;
short c[3];
};
int main(){
	cout<<sizeof(A);//24=10+2+4+3*2+2
}*/

//

/*
STL中的哪种结构在增加成员时可能会引起原有成员的存储位置发生:
正确答案: D   

A,map;
B,set;
C,list;
D,vector;
*/

//
/*
#include<stdio.h>
struct node{
    int elem;
    struct node* next;
}; 
void difference(node** LA,node* LB){
    node*pa,*pb,*pre,*q;
    pre=NULL;
    pa=*LA;// LA是指向指针的指针,pa指向集合的元素
    while(pa){
        pb=LB;// pb指向集合B的元素
        while(pb && pa->elem!=pb->elem) //在链表LB中寻找与pa所指元素相等的节点
            pb=pb->next;
        if(pb){ // pa所指元素与pb所指元素相等
            if(!pre){
                *LA=pa->next;
            }else{
                pre->next=pa->next;
            }
            q=pa;// 求差集 所以要删除pa节点
            pa=pa->next;
            free(q);
        }else{
            pre=pa;
            pa=pa->next;
        }
    }
}

    本题的解法思路较简单:
    因为要求集合A和集合B的差集(A-B),结果保存在集合A中.
    所以我们取出集合A中每一个元素,然后在集合B中寻找(代码22行所实现) 找到即删除此节点 否则保留
    此时while循环跳出只有两种情况,pb为NULL或者 pa->elem==pb->elem
    当pb不为null时,即找出集合A和集合B的公有元素,此时要删除这个元素
        pre(实现删除节点之后的链接)
        当pre为NULL时,说明是首次找到A和B的公有元素,此时 *LA指向pa->next 所以*LA仍然是头结点
        当pre不为NULL时, pre指向pa->next,顺利实现删除节点的链接
*/
//

//函数可以嵌套调用,但不可以嵌套定义。

/*
class A
{
    int _a;
public:
    A(int a): _a(a)
    {
    }
    friend int f1(A &);
    friend int f2(const A &);
    friend int f3(A);
    friend int f4(const A);
};
以下调用哪个是错误的:
正确答案: A   非常量引用的初始值必须为左值

f1(0)
f2(0)
f3(0)
f4(0)
*/

//


/*
下面有关malloc和new,说法错误的是? 
正确答案: C   

A new 建立的是一个对象, malloc分配的是一块内存.
B new   初始化对象,调用对象的构造函数,对应的delete调用相应的析构函数,malloc仅仅分配内存,free仅仅回收内存
C new和malloc都是保留字,不需要头文件支持
D new和malloc都可用于申请动态内存,new是一个操作符,malloc是是一个函数

new/delete都是要分两步操作的:new分配内存,并且调用对象的构造函数初始化一个对象;delete调用相应的析构函数,然后释放内存
malloc/free只是分配内存/回收内存, 所以A、B对;
malloc需要头文件"stdlib.h"或者"malloc.h" C错;
new/delete都是内建的操作符,而malloc是一个函数,其函数原型是:
1
void *malloc(unsigned int num_bytes);
所以选C
*/

//

/*
union Test
 {
    char a[4];
    short b;
 };
 Test test;
 test.a[0]=256;
 test.a[1]=255;
 test.a[2]=254;
 test.a[3]=253;
 printf("%d\n",test.b);
 在80X86架构下,输出什么值?
 -128
-256
128
256
 char类型的取值范围是-128~127,unsigned char的取值范围是0~256
这里a[0]=256,出现了正溢出,将其转换到取值范围内就是0,即a[0]=0;
同理,a[1]=-1, a[2]=-2, a[3]=-3,在C语言标准里面,用补码表示有符号数,故其在计算机中的表示形式如下:
a[0]=0,     0000 0000
a[1]=-1,    1111 1111
a[2]=-2,    1111 1110
a[3]=-3,    1111 1101
short是2字节(a[0]和a[1]),由于80X86是小端模式,即数据的低位保存在内存的低地址中,
而数据的高位保存在内存的高地址中,在本例中,a[0]中存放的是b的低位,a[1]中存放的是b的高位,
即b的二进制表示是:1111 1111 0000 0000,表示-256,故选B。
*/

//
/*
char *c[] = { "ENTER", "NEW", "POINT", "FIRST" }; 
char **cp[] = { c+3, c+2, c+1, c }; 
char ***cpp = cp; 

int main(void)
{ 
	printf("%s", **++cpp); 
	printf("%s", *--*++cpp+3); 
	printf("%s", *cpp[-2]+3); 
	printf("%s\n", cpp[-1][-1]+1); 
	return 0;
}
输出POINTERSTEW
http://blog.csdn.net/yuanjilai/article/details/8043784
*/ 

//

/*
#include<iostream>
using namespace std;
class A{
	public:
	const static int a=1;
};
int main(){
	A a1;
	cout<<a1.a<<" "<<A::a; 
}
通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.
初始化时使用作用域操作符来指出静态成员所属的类.
但如果静态成员是整型或是枚举型const,则可以在类声明中初始化!! 
*/


/*
#include<iostream>
using namespace std;
struct A{
  void foo(){printf("foo");}
  virtual void bar(){printf("bar");}
  A(){bar();}
};
struct B:A{
  void foo(){printf("b_foo");}
  void bar(){printf("b_bar");}
};
int main(){
	A *p=new B;
	//p->foo();
	//p->bar();
}*/


//

/*
在C++STL中常用的容器和类型,下面哪些支持下标"[]"运算?
vector
list
deque
map
set
unordered_map
unordered_set
stack
string

ACDFI
vector:随机访问迭代器,复杂度O(1)
deque:同上,O(1)
map:双向迭代器,不过由于是关联容器,需要通过key访问value的方法,O(h),h为树的高度
unordered_map:前向迭代器,同上,平摊复杂度O(1),最差O(n),也与散列函数的好坏有关。
string:同vector
*/


//

/*
class ClassA
{
    public:
    virtual ~ ClassA()
    {
    }
    virtual void FunctionA()
    {
    }
};
class ClassB
{
    public:
    virtual void FunctionB()
    {
    }
};
class ClassC: public ClassA, public ClassB
{
    public:
};
ClassC aObject;
ClassA *pA = &aObject;
ClassB *pB = &aObject;
ClassC *pC = &aObject;

假设定义了ClassA* pA2,下面正确的代码是:
正确答案: B D   

A pA2=static_cast<ClassA*>(pB);
B void* pVoid=static_cast<void*>(pB);
  pA2=static_cast<ClassA*>(pVoid);
C pA2=pB;
D pA2=static_cast<ClassA*>(static_cast<ClassC*>(pB));

A   两个无关类型指针之间的转换 是不合法的
B  通过void*这个媒介 ,合法
C  直接赋值,无法进行隐式转换,不合法
D  通过继承体系中的一个 做媒介, 上行 下行 合法
四类强制转换:
static_cast(编译器可实现的隐式转换或类层次间的下行转换)、
dynamic_cast(操作数只能为类指针或类引用)、
const_cast(去除const)、
reinterpret_const(一般意义强制转换)

static_cast 的用法
static_cast < type-id > ( expression )
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性。

C++中的static_cast执行非多态的转换,用于代替C中通常的转换操作。因此,被做为显式类型转换使用。

C++中的reinterpret_cast主要是将数据从一种类型的转换为另一种类型。所谓“通常为操作数的位模式提供较低层的重新解释”
也就是说将数据以二进制存在形式的重新解释。

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值