C++小题(十五)

来源:互联网 发布:淘宝网店客服怎么做 编辑:程序博客网 时间:2024/05/01 09:05
/*有如下程序段:#include <iostream>using namespace std; class A {    public:    ~A() {        cout << "~A()";    }};class B{    public:    virtual ~B() {    cout << "~B()";}};class C: public A, public B {    public:    ~C() {        cout << "~C()";    }};int main() {    C * c = new C;    B * b1 = dynamic_cast<B *>(c);    A * a2 = dynamic_cast<A *>(b1);    delete a2;}则程序输出:正确答案: D   你的答案: D (正确)~C()~B()~A()~C()~A()~B()A)B)都有可能以上都不对创建一个类对象c,然后动态类型转换,让一个B *b1指针指向c,再一次动态类型转换,让一个基类A *a2指针指向b1,当delete a2时,调用析构函数,但是基类A的析构函数不是虚函数,所以只调用A的析构函数,结果应该是:~A()*////////////////////////////////////////////////////////////////////////////////*在x86的机器上,int a=0xabcd1234 char b=((char*)&a)[0]请问b是多少正确答案: D   你的答案: D (正确)0xa0x40xab0x3486是小端存储,即高位存储在高地址,低位存储在低地址。int a = 0xabcd1234;内存中 ab  cd  12   34,b作为一个char,右边表达式指针指向为0x34.       高  -->      低*////////////////////////////////////////////////////////////////////////////////*以下描述错误的是:正确答案: B   你的答案: C (错误)A函数的形参在函数未调用时不分配存贮空间B若函数的定义出现在主函数之前,则可以不必再说明C若一个函数没有return语句,返回类型是voidD一般来说,函数的形参和实参的类型应该一致函数定义在主函数之前...仅仅是说明主函数调用这个函数不会有问题...但是如果函数前还有其他函数调用这个函数就有问题了*////////////////////////////////////////////////////////////////////////////////*struct Date{    char a;    int b;    int64_t c;    char d;};Date data[2][10];在32位系统上,如果Data的地址是x,那么data[1][5].c的地址是()正确答案: C   你的答案: C (正确)X+195X+365X+368X+215结构体成员地址对齐a               b  c  d1+(3)+4+8+1+(7)= 24,()内表示为了满足对齐填充的大小。&data[1][5].c = x+10*24+5*25+1+(3)+4=368。 *////////////////////////////////////////////////////////////////////////////////*下列哪个用法那个是错误的( )正确答案: B   你的答案: B (正确)typedef void (*FUN)();const int &ra;extern const int array[256];int* a;引用类型是要设定初值的。 指针不用。*////////////////////////////////////////////////////////////////////////////////*以下代码编译有错误,哪个选项能解决编译错误?class A {    public:        int GetValue() const {            vv = 1;            return vv;         }    private:        int vv;};正确答案: D   你的答案: D (正确)A改变成员变量"vv"为"mutable int vv"B改变成员函数"GetValue"的声明,以使其不是const的C都不能修复编译错误D都可以修复编译错误mutalbe的中文意思是“可变的,易变的”,跟constant(既 C ++中的const)是反义词。 在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。 我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的。但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰。*////////////////////////////////////////////////////////////////////////////////*C++内存分配中说法错误的是:______。正确答案: A   你的答案: A (正确)a对于栈来讲,生长方向是向上的,也就是向着内存地址增加的方向b对于堆,大量的 new/delete 操作会造成内存空间的不连续c堆容易产生 memory leakd堆的效率比栈要低得多e栈变量引用容易逃逸f以上都对栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将 提示overflow。因此,能从栈获得的空间较小。    堆:堆是向高地址扩展的数据结构,是不连续的内存区域。 这是由于系统是用链表来存储  的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。 堆的大小  受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。 *////////////////////////////////////////////////////////////////////////////////*下面的说法那个正确#define NUMA 10000000#define NUMB 1000int a[NUMA], b[NUMB];  void pa(){    int i, j;    for(i = 0; i < NUMB; ++i)        for(j = 0; j < NUMA; ++j)            ++a[j];}void pb(){    int i, j;    for(i = 0; i < NUMA; ++i)        for(j = 0; j < NUMB; ++j)            ++b[j];}正确答案: C   你的答案: B (错误)pa 和 pb 运行的一样快pa 比 pb 快pb 比 pa 快无法判断一般情况下,我们认为把大的循环放在里面,效率会比较高但是当如此题一样,涉及不同的内存存取时,把大的循环放在外面可以增大缓存命中率,大幅提高效率。测试时pb比pa快,数组a比数组b大很多,可能跨更多的页,缺页率高或者缓存命中更低,所以pb快*////////////////////////////////////////////////////////////////////////////////*使用操作符 对数据进行格式输出时,应包含( )文件。正确答案: D   你的答案: D (正确)fstream.hstdlib.hiostream.hiomanip.h*////////////////////////////////////////////////////////////////////////////////*建立派生类对象时,3种构造函数分别是a(基类的构造函数)、b(成员对象的构造函数)、c(派生类的构造函数)这3种构造函数的调用顺序为: 正确答案: A   你的答案: A (正确)abcacbcabcba*////////////////////////////////////////////////////////////////////////////////*分析以下函数,该函数的功能是()void sca_from_file(int a[], int n, char fn[]){    FILE *fp;    int i;    fp = fopen(fn, "r");    for (i = 0; i < n; i++)    {        fscanf(fp, "%d", &a[i]);    }    fclose(fp);}正确答案: A   你的答案: A (正确)打开文件fn,从文件中读出n个整数到数组a中打开文件fn,将数组a的n个元素写到文件中打开文件fn,从文件中读出n,再读n个整数到数组a中打开文件fn,将n和数组a的n个元素依次写到文件中*////////////////////////////////////////////////////////////////////////////////*下面关于typedef char *String_t; 和#define String_d char * 这两句在使用上的区别描述错误的是?正确答案: C   你的答案: C (正确)typedef char *String_t 定义了一个新的类型别名,有类型检查#define String_d char * 只是做了个简单的替换,无类型检查前者在预编译的时候处理,后者在编译的时候处理同时定义多个变量的时候有区别,主要区别在于这种使用方式String_t a,b; String_d c,d; a,b ,c 都是char*类型,而d 为char 类型*////////////////////////////////////////////////////////////////////////////////*下列关于C语言中指针的说法错误的是:___正确答案: B   你的答案: C (错误)a指针的值是一个地址b非法指针是指该指针的值不是一个已经分配的内存地址c两个指向同类型地址的指针之间做减法一般是没有意义的d指针的指针占用的内存空间和其他指针占用的内存空间相同非法指针是指向的内存已经被回收,或者指向一个错误的地址。*////////////////////////////////////////////////////////////////////////////////*1<<3+2的值是()。32运算符+的优先级高于左移<<*////////////////////////////////////////////////////////////////////////////////*有如下几个类和函数定义,选项中描述正确的是:【多选】()class A {    public:    virtual void foo() {}    //…};class B {    public:    virtual void foo() {}    //…};class C    : public A    , public B {    public:    virtual void foo() {}    //…};void bar1(A * pa) {    B * pc = dynamic_cast<B * >(pa);    //…}void bar2(A * pa) {    B * pc = static_cast<B * >(pa);    //…}void bar3() {    C c;    A * pa = & c;    B * pb = static_cast<B * >(static_cast<C * >(pa));    //…}bar1无法通过编译bar2无法通过编译bar3无法通过编译bar1可以正确运行,但是采用了错误的cast方法类A、B没有继承关系,所以使用static_cast是错误的。至于D选项,因为使用了dynamic_cast<> 即是转换不成功也只是返回NULL而不是错误。并且在这dynamic_cast<> 也是可以使用的。C++ 类型转换 dynamic_cast<> 运行时类型识别 RTTI1. dynamic_cast<>dynamic_cast<>用于C++类继承多态间的转换,分为3中:1.子类向基类的向上转型(Up Cast)2.基类向子类的向下转型(Down Cast)3.横向转型(Cross Cast)其中向上转型不需要借助任何特殊的方法,只需用将子类的指针或引用赋给基类的指针或引用即可,dynamic_cast向上转型其总是肯定成功的。而向下转换时要特别注意:dynamic_cast操作符,将基类类型的指针或引用安全的转换为派生类的指针或引用。dynamic_cast将一个基类对象指针(或引用)cast到继承类指针,dynamic_cast会根据基类指针是否真正指向继承类指针来做相应处理。这也是dynamic_cast与其他转换不同的地方,dynamic_cast涉及运行时类别检查,如果绑定到引用或指针的对象不是目标类型的对象,则dynamic_cast失败。如果是指针类型失败,则dynamic_cast的返回结果为0,如果是引用类型的失败,则抛出一个bad_cast错误。注意:dynamic_cast在将父类cast到子类时,父类必须要有虚函数。因为dynamic_cast运行时需要检查RTTI信息。只有带虚函数的类运行时才会检查RTTI。RTTI(Run-Time Type Identification),通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。RTTI提供了以下两个非常有用的操作符:(1)typeid操作符,返回指针和引用所指的实际类型。(2)dynamic_cast操作符,将基类类型的指针或引用安全地转换为派生类型的指针或引用。*////////////////////////////////////////////////////////////////////////////////*以下选项中合法的实型常量是?正确答案: C   03.13e-2.1.9142.0*10实型常量又称实数或浮点数。在C语言中可以用两种形式表示一个实型常量。小数形式        小数形式是由数字和小数点组成的一种实数表示形式,例如0.123、.123、123.、0.0等都是合法的实型常量。        注意:小数形式表示的实型常量必须要有小数点。指数形式        这种形式类似数学中的指数形式。在数学中,一个可以用幂的形式来表示,如2.3026可以表示为0.23026×10^1 2.3026×10^0 23.026×10^-1等形式。在C语言中,则以“e”或“E”后跟一个整数来表示以“10”为底数的幂数。2.3026可以表示为0.23026E1、2.3026e0、23.026e-1。C语言语法规定,字母e或E之前必须要有数字,且e或E后面的指数必须为整数。如e3、5e3.6、.e、e等都是非法的指数形式。注意:在字母e或E的前后以及数字之间不得插入空格。        程序运行的过程中,其值不能被改变的量称为常量。常量有不同类型,其中12、0、-5为整型常量。'a''b'为字符常量。而4.6、-8.7则为实型常量。        一个实型常量可以赋给一个 float 型、double 型或 long double 变量。根据变量的类型截取实型常量中相应的有效位数字。*////////////////////////////////////////////////////////////////////////////////*给出以下定义, 则正确的叙述为char x[]="abcdefg";char y[]={'a','b','c','d','e','f','g'};正确答案: C   你的答案: C (正确)数组X和数组Y等价数组X和数组Y长度相同数组X的长度大于数组Y的长度数组X的长度小于数组Y的长度char x[]="abcdefg";中会隐式的在末尾添加空字符,C语言对字符串常量,自动追加'\0';而char y[]={'a','b','c','d','e','f','g'},是字符数组,则不会添加,空字符的出现取决于系统中空字符的出现,这种定义下不是一个字符串。*////////////////////////////////////////////////////////////////////////////////*下列关于联合的描述中,错误的是?正确答案: A   你的答案: A (正确)联合变量定义时不可初始化联合的成员是共址的联合的成员在某一个时刻只有当前的是有效的联合变量占有的内存空间是该联合成员占有最大内存空间的成员所需的存储空间union类型的变量在定义时是可以被初始化的,定义如下union类型union Test{    int a;    float b;};Test test = {1};test变量的定义可以初始化,初始值的类型必须是union中第一个成员的类型。*////////////////////////////////////////////////////////////////////////////////*定义网络传输数据包为 class packet{     int size;     void data[0];}其中data的作用是?正确答案: C   维护数据包空间的连续性数据分割位指向独立的数据空间无任何作用*////////////////////////////////////////////////////////////////////////////////*32位机器上定义如下结构体:struct xx{    long long _x1;    char _x2;    int _x3;    char _x4[2];    static int _x5;};int xx::_x5;1请问sizeof(xx)的大小是()正确答案: D   你的答案: D (正确)19201524*////////////////////////////////////////////////////////////////////////////////*下列关于异常处理的描述中,理解不正确的是:正确答案: D   C++语言的异常处理机制通过3个保留字throw、try和catch实现。任何需要检测的语句必须在try语句块中执行,并由throw语句抛出异常。throw语句抛出异常后,catch利用数据类型匹配进行异常捕获。一旦catch捕获异常,不能将异常用throw语句再次抛出。A,正确,throw是抛出异常关键字,try是尝试执行可能有异常代码的关键字,catch是捕获异常的关键字B,正确,可能抛出异常的代码块都应该放在try代码块中C,正确,catch捕获相应的异常,可以有多级catch代码块来捕获不同级别的异常D,被捕获的异常可以再次抛出*////////////////////////////////////////////////////////////////////////////////*以二进制方式打开一个文件的方法是?正确答案: C   FILE *f = fwrite( "test.bin", "b" );FILE *f = fopenb( "test.bin", "w" );FILE *f = fopen( "test.bin", "wb" );FILE *f = fwriteb( "test.bin" );以二进制打开文件方式得加上b*////////////////////////////////////////////////////////////////////////////////*类模板的使用实际上是类模板实例化成一个具体的__________。正确答案: A   类函数模板类对象*////////////////////////////////////////////////////////////////////////////////*char *p1;int64 *p2;p1=(char *)0x800000;p2=(int64 *)0x800000;char *a=p1+2int64_t *b=p2+2那么a= 1 ,b= 2 0x8000020x800010///////////////////////////////////////////////////////////////////////////////*有如下程序段:12char ch=-1;printf(“%02x,%02x”,ch,(unsigned char)ch);则输出:正确答案: C  -1,-1ff,ffffffffff,ffff,ffffffff%02x表示输出最少2位,不足补0.第一个ch=-1,负数拓展到32位需要补1,所以是ffffffff第二个先转换为无符号数ff(255), 正数拓展补0,由于最少输出2位,所以是ff*////////////////////////////////////////////////////////////////////////////////*有定义语句:12int b;char c[10];则正确的输入语句是______。正确答案: B   scanf("%d%s",&b,&c);scanf("%d%s",&b,c);scanf("%d%s",b,c);scanf("%d%s",b,&c);*////////////////////////////////////////////////////////////////////////////////*In the main() function, after ModifyString(text) is called, what’s the value of ‘text’?int FindSubString( char* pch ){    int   count  = 0;    char  * p1   = pch;    while ( *p1 != '\0' )    {           if ( *p1 == p1[1] - 1 )        {            p1++;            count++;        }else  {            break;        }    }    int count2 = count;    while ( *p1 != '\0' )    {        if ( *p1 == p1[1] + 1 )        {            p1++;            count2--;        }else  {            break;        }    }    if ( count2 == 0 )        return(count);    return(0);}void ModifyString( char* pText ){    char  * p1   = pText;    char  * p2   = p1;    while ( *p1 != '\0' )    {        int count = FindSubString( p1 );        if ( count > 0 )        {            *p2++ = *p1;            sprintf( p2, "%i", count );            while ( *p2 != '\0' )            {                p2++;            }            p1 += count + count + 1;        }else  {            *p2++ = *p1++;        }    }}void main( void ){    char text[32] = "XYBCDCBABABA";    ModifyString( text );    printf( text );}  正确答案: C   XYBCDCBABABAXYBCBCDA1BAAXYBCDCBA1BAAXYBCDDBA1BABFindSubString函数查找"对称!!!"的连续上升再连续下降回文子串(例如CDC,题目中的BCDCBA不是),返回count,若不是回文子串或者不对称则返回0字符串XYBCDCBABABA 之前的所有字符执行的都是 ModifyString函数中的else子段,即*p2++=*p1++;字符串 XYBCDCBABABA 的 第一个对称回文子串为ABA,此时sprintf语句会用count(此时为1)替换B,并自动添加串结尾符'\0'在第二个A的位置,则下边的while语句即将p2指针移动到第二个A的位置,p1 += count + count +1将p1移动到第二个A后面的B位置上,即p2的后一位这之后没有对称回文子串,则执行*p2++=*p1++,直到p1到达串尾,即用倒数第二个字符替换倒数第三个,用倒数第一个字符替换倒数第二个综上,结果是XYBCDCB A1 BA A原型int sprintf( char *buffer, const char *format, [ argument] … );功能:把格式化的数据写入某个字符串缓冲区。头文件stdio.h参数列表buffer:char型指针,指向将要写入的字符串的缓冲区。format:格式化字符串。[argument]...:可选参数,可以是任何类型的数据。返回值:字符串长度(strlen)*////////////////////////////////////////////////////////////////////////////////*以下代码运行结果为()#include<stdio.h>int main(){    uint32_t a = 100;    while (a > 0)    {        --a;    }    printf("%d", a);    return 0;}正确答案: C   -11000死循环Unsigned int型数字最小为0,因此不是死循环,a到0就跳出循环,最后输出0*////////////////////////////////////////////////////////////////////////////////*若以下选项中的变量a,b,y均以正确定义并赋值,则语法正确的switch语句是?正确答案: A B   switch(a*a+b*b){ default:break;case3 : y=a+b; break;case2 : y=a-b; break;}switch(a+b){ case1 : case3 : y=a+b;break;case0 : case4 : y=a-b;}switch(a+9){ case a : y=a-b;case b : y=a+b;}switch a*b{ case 10 : y=a+b;default : y=a-b;}C选项中case a和case b不正确,case后面应该跟常量表达式;D选项中,switch a*b,有误*////////////////////////////////////////////////////////////////////////////////*拷贝构造函数的特点是()正确答案: B D   a该函数名同类名,也是一种构造函数,该函数返回自身引用b该函数只有一个参数,必须是对某个对象的引用c每个类都必须有一个拷贝初始化构造函数,如果类中没有说明拷贝构造函数,则编译器系统会自动生成一个缺省拷贝构造函数,作为该类的保护成员d拷贝初始化构造函数的作用是将一个已知对象的数据成员值拷贝给正在创建的另一个同类的对象拷贝函数和构造函数没有返回值,A错;拷贝构造函数的参数可以使一个或多个,但左起第一个必须是类的引用对象,B错;若类定义中没有声明拷贝构造函数,则编译器会自动生成一个缺省的拷贝构造函数,但是不会是该类的保护成员,C错;通过拷贝函数可以将另一个对象作为对象的初值,D对*////////////////////////////////////////////////////////////////////////////////*有如下程序段:char a[] = "xyz", b[] = {'x', 'y', 'z'};if (strlen(a) > strlen(b))    printf("a > b\n");else    printf("a <= b\n");则程序输出:正确答案: B   你的答案: B (正确)a>ba<=b编译不通过以上都不对在release模式下,strlen(b)是确定的,因为局部变量压栈是连续的,这样 strlen(b)就是6;但是在debug模式下,因为变量在内存中并不连续,所以 strlen(b)不确定*////////////////////////////////////////////////////////////////////////////////*下列程序的输出结果是#include<iostream>using namespace std; int main(){    char p1[10] = "abcd", *p2, str[10] = "xyz";        p2 = "ABCD";    strcpy(str + 2, strcat(p1 + 2, p2 + 1));    printf(" %s", str);}正确答案: D   你的答案: D (正确)xyabcABabcABzABabczxycdBCDstrcat(p1 + 2, p2 + 1)表示将p2+1所指字符串"BCD"拼接在"cd"字符串后面形成"cdBCD";strcpy(str + 2, "cdBCD");将字符串拷贝到str +2 的位置形成"xycdBCD"*////////////////////////////////////////////////////////////////////////////////*以下程序段执行后结果是()#include<stdio.h>void main(){    short *p,*q;    short arr[15]={0};    p=q=arr;    p++;    printf("%d,",p-q);    printf("%d,",(char*)p-(char*)q);    printf("%d",sizeof(arr)/sizeof(*arr));}正确答案: D   你的答案: D (正确)1,0,151,2,11,1,151,2,15指针自增、自减每次移动的偏移量是指针所指向对象的字节大小,所以p++与q的偏移量是2个字节。指针相减的值是指针地址的偏移除以指针每次移位的大小;1)p-q=1;偏移量为2个字节,每次移动2个字节,所以为12)(char *)p-(char *)q,指针的偏移没变,但是每次指针移位是按照(char*)类型移动,即每次移动1个字节,所以是23)数字每次元素2个字节,所以sizeof(arr)为30,sizeof(*arr)为2。*////////////////////////////////////////////////////////////////////////////////*若有以下程序#include<stdio.h>main(){     int s=0,n;    for(n=0; n<4; n++)    {        switch(n)        {           default:s+=4;           case 1:s+=1;           case 2:s+=2;           case 3:s+=3;        }    }    printf ("%d\n",s);}则程序的输出结果是?正确答案: D   你的答案: D (正确)6181024第一次循环for循环,n的值为0,所以从default后面的语句开始执行,s+=4,s+=1,s+=2,s+=3,s的值为10。在进入第二次for循环,n的值为1,所以执行的s+=1,s+=2,s+=3,s的值为16。在进入第三次for循环,n的值为2,所以执行s+=2,s+=3,s的值为21。在进入第四次for循环,n的值为3,所以执行s+=3,s的值为24。*////////////////////////////////////////////////////////////////////////////////*针对以下代码,const char str1[] = "abc";const char str2[] = "abc";const char *p1 = "abc";const char *p2 = "abc";判断下列说法哪个是正确的()正确答案: A   你的答案: A (正确)str1和str2地址不同,P1和P2地址相同str1和str2地址相同,P1和P2地址相同str1和str2地址不同,P1和P2地址不同str1和str2地址相同,P1和P2地址不同4个地址都相同4个地址都不同 str1和str2是栈空间中的两个字符数组,地址不同p1和p2指向的位置在常量区,值都是“abc”所以是同一常量,地址相同*////////////////////////////////////////////////////////////////////////////////*下列哪两个是等同的   int b;   1.const int *a = &b;   2.const * int a = &b;   3.const int* const a = &b;   4.int const* const a = &b;第二个 语法错误int const *a 和 const int *a 意义相同,作用等价 同理,本题3、4意义相同const int *a  这里const 修饰的是int,而int定义的是一个整值int *const a   这里const修饰的是 a ,a代表的是一个指针地址  因此不能赋给a其他的地址值,但可以修改a指向的值const int * const a  这个代表a所指向的对象的值以及它的地址本身都不能被改变  *///////////////////////////////////////////////////////////// /*以下哪些做法是不正确或者应该极力避免的:【多选】( )正确答案: A C D   你的答案: A C D (正确)构造函数声明为虚函数派生关系中的基类析构函数声明为虚函数构造函数中调用虚函数析构函数中调用虚函数如果构造函数设为虚函数,那么当你在构造父类的构造函数时就不得不显示的调用构造,还有一个原因就是为了防错,试想如果你在子类中一不小心重写了个跟父类构造函数一样的函数,那么你的父类的构造函数将被覆盖,也即不能完成父类的构造.就会出错.在构造函数不要调用虚函数。在基类构造的时候,虚函数是非虚,不会走到派生类中,既是采用的静态绑定。显然的是:当我们构造一个子类的对象时,先调用基类的构造函数,构造子类中基类部分,子类还没有构造,还没有初始化,如果在基类的构造中调用虚函数,如果可以的话就是调用一个还没有被初始化的对象,那是很危险的,所以C++中是不可以在构造父类对象部分的时候调用子类的虚函数实现。但是不是说你不可以那么写程序,你这么写,编译器也不会报错。只是你如果这么写的话编译器不会给你调用子类的实现,而是还是调用基类的实现。在析构函数中也不要调用虚函数。在析构的时候会首先调用子类的析构函数,析构掉对象中的子类部分,然后在调用基类的析构函数析构基类部分,如果在基类的析构函数里面调用虚函数,会导致其调用已经析构了的子类对象里面的函数,这是非常危险的。  */

0 0