C++易错总结(持续更新)

2024-05-08 15:38
文章标签 c++ 总结 更新 持续 易错

本文主要是介绍C++易错总结(持续更新),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、以下涉及到内存管理的代码中,有错误的是:

A:

int *a=new int(12);
//......
free(a);

B:

int *ip=static_cast<int *>(malloc(sizeof(int)));
*ip=10;
//......
delete ip;

C;

double *a=new double[1];
//.....
delete a;

D;

int *ip=new int(12);
for(int i=0;i<12;i++)
{ip[i]=i;
}
delete [] ip;

解析:new和delete搭配,malloc和free搭配,所以A B错误。

   关于D,要注意new int[12] 和new int (12)的区别,new int[12]生成一个大小为12 的int数组,而new int(12)是生成一个初始值为12的int变量。所以D错

       关于C,乍一看,a是一个数组,应该用delete [ ] a,但是对于基本类型数组来说,delete a和delete [ ] a效果是一样的,如果a是一个用户自己定义的结构类型数组,只能            使用delete [ ] a。

2、如下代码,result变量的输出结果是多少?

#include<iostream>
using namespace std;
int i=1;
class MyCls
{public:MyCls():m_nFor(m_nThd),m_nSec(i++),m_nFir(i++),m_nThd(i++){m_nThd=i;}void echo(){cout<<"result"<<m_nFir+m_nSec+m_nThd+m_nFor<<endl;}private:int m_nFir;int m_nSec;int m_nThd;int &m_nFor;
};int main()
{MyCls oCls;oCls.echo();return 0;
}
解析:首先要明白, 变量初始化的顺序是其声明的顺序,跟初始化列表中的顺序无关,所以变量的初始化顺序m_nFir(i++),m_nSec(i++),m_nThd(i++),m_nFor(m_nThd),i初始化为1,所以经过初始化列表后的m_nFir=1,m_nSec=2,m_nThd=3,m_nFor是m_nThd的一个引用,并且此时i的值为4,执行构造函数中的赋值语句后,m_nThd=4,此时m_nFor是m_nThd的一个引用,也是4。result=1+2+4+4=11。

3、由多个源文件组成的C程序,经过编辑、预处理、编译、链接等阶段会生成最终的可执行程序,下面哪个阶段会发现被调用的函数没有定义?

A:预处理           B:编译            C:链接           D:执行

解析:预处理阶段主要是对各种预处理命令的处理,包括头文件的包含、宏定义的扩展、条件编译的选择等

    编译阶段进行c词法和语法的分析,首先编译成纯汇编语句,再汇编程二进制码,再生成各个目标文件

   链接阶段,到了链接阶段才会知道各个函数的调用关系,才能出现调用某个函数但是该函数没有声明的情况。

4、下面哪个指针表达式 可以用来引用数组元素a[i][j][k][l]?

A:((((a+i)+j)+k)+l)        B:*(*(*((a+i)+j)+k)+l)          C:(((a+i)+j)+k+l)          D:((a+i)+j+k+l)

解析: 如果a是一个指向四维数组的指针,那么*a就指向的是一个三维数组,**a只想一个二维数组,***a指向一个三维数组,****a指向某个元素。

5、下面的代码会输出:

int main()
{	int a[4]={1,2,3,4};int *ptr=(int *)(&a+1);printf("%d",*(ptr-1));
}
解析:最终结果会输出4。考察数组和指针, 指针加一的能力由指针指向的类型决定。&a和a都指的是数组首元素的地址,不同的是,a就是a+0,*(a+0)也就是a[0],而&a+1相当于对a[]类型的数组类型的指针加一,此时指针加到数组的末尾。ptr接受之后,ptr指向最后一个元素后面的那个位置,而ptr的类型是int*,因此,ptr-1之后指向数组最后一个元素4。

5、下面哪个用法是错误的

        A:int *a                   B:extern const int array[256]               C:const int &a            D:typedef void (*FUN)()

解析:C错误,原因是引用定义的时候必须对其进行初始化。指针不是必须初始化,而引用是在定义的时候必须对其进行初始化。对于D,其实D定义的是一个函数指针数据类型,通过FUN foo就定义一个指向的函数参数列表为空,返回值为空的函数。详见:http://blog.csdn.net/zhangleo1987/article/details/5707290

6、有下面一段程序,则下列不合法的是

int f1(float);
int f2(char);
int f3(float);
int f4(float);
int (*pf)(float)
A:int (*p)(float)=&f1             B:pf=&f4             C:pf=&f2                  D:pf=f3
解析:C错误,原因是函数参数类型不匹配。函数指针声明的方法:  返回值类型   (*指针变量名)([参数列表])

根据定义,则int (*pf)(float)                           int (*p)(float)=&f1     ,pf和p都是函数指针。对于函数地址的获取,可以是函数名,也可以是函数名前加取地址符&。

7、若有下列定义语句,则以下赋值语句错误的是:

     定义

char s[3][10];
char (*k)[3];
char *p;
    赋值:

1.p=s;
2.p=k;
3.p=s[0];
4.k=s;
解析:s是一个二维数组,也可以看成是一个一维数组,这个一维数组的每个元素是一个包含10个元素的一维数组,s指向这个包含三个元素的一维数组的第一个元素,也就是s中的第一个一维数组的第一个元素。k是一个指向有三个cha元素的数组指针。p是一个指向char变量的指针。所以1、2、4都是错误的。3是正确的,因为s[0]就指向一个一维数组。

8、math.h中abs返回值()

解析:abs的返回值可能是正数,可能是负数,可能是0。因为负数的范围比正数的范围大一。比如,8位二进制数范围是-128~+127,abs(-128)不可能返回128,只能返回原值,也就是-128,但是其他正数、负数、零都按正常取绝对值返回。

9、以下代码的执行结果是:

int _tmain(int argc, _TCHAR* argv[])
{int i=-2147483648;printf("%d  %d  %d  %d",~i,-i,1-i,-1-i);cin.get();return 0;
}
解析:-2147483648是32位int所能表示的最小负整数,其用原码表示为1000  0000  0000  0000  0000  0000  0000  0000,,最小负整数原码和补码表示一样。

           ~i:表示按位取反,为 0111 1111  1111 1111  1111  1111 1111 1111,符号位为0,表示正数,原码补码一样,2147483647

    -i:对数值执行单目运算符-表示对该数按位取反(包括符号位)再+1,也就是求补运算注意求补运算和求补码的不同,求补码是对数值位(不包括符号位)取反再+1,求补运算时按位取反(包括符号位)再+1。对i=1000  0000  0000  0000  0000  0000  0000  0000求补再+1还是得到1000  0000  0000  0000  0000  0000  0000  0000,也就是-2147483648。

    1-i:1-i等价于1+(-i),1000  0000  0000  0000  0000  0000  0000  0000+0000  0000  0000  0000  0000  0000  0000  0001=1000  0000  0000  0000  0000  0000  0000  0001,该补码表示的原码是1111 1111  1111 1111  1111  1111 1111 1111,也就是-2147483647.

     -1-i:等价于-1+(-i),-1的补码为:1111  1111  1111  1111  1111  1111  1111  1111,加上i的补码1000  0000  0000  0000  0000  0000  0000  0000,得到0111  1111  1111  1111  1111  1111  1111  1111,该补码表示的原码是他本身,也就是2147483647.

             总结:正数的原码、反码、补码形式一致,负数的反码为原码的数值位(不包括符号位)按位取反,补码为反码+1,计算机中以补码表示数据和运算,而32位最小负整数的补码为1000  0000  0000  0000  0000  0000  0000  0000。

10、以下程序段执行后结果是:

#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));
}
解析:short占两个字节,指针加一的能力由指针指向的类型决定,所以p++与q的偏移量就是2个字节。short arr[15]={0}是初始化所有数组元素为0, 指针相减的结果是指针地址的偏移量除以指针每次移位的大小。

    p-q:偏移量为2个字节,每次移动2个字节,所以p-q=1

            (char*)p-(char*)q:偏移量还是2个字节,但是每次指针移位按照char*移位,也就是每次移动1个字节,所以(char*)p-(char*)q=2;

    对数组名取sizeof()得到的是整个数组的大小,所以sizeof(arr)=15*2=30,;*arr指向数组的第一个元素,所以sizeof(*arr)=2,sizeof(arr)/sizeof(*arr)=15

11、下列程序段执行后,输出的结果为:

void  main()
{int a=1,b=0,c=-1,d=0;d=++a||++b&&++c;cout<<d<<endl;
}
解析: 短路原则:||操作符左操作数为真,即可停止判断,右操作数不再执行。因此本题最后结果a=2,b=0,c=-1,d=1。

12、
下列程序执行结果是:

#include<iostream>
using namespace std;
class TestClass
{char x;
public:TestClass(){cout<<'A';}TestClass(char a){cout<<a;}~TestClass(){cout<<'B';}
};
int  main()
{TestClass p1,*p2;p2=new TestClass ('X');delete p2;return 0;
}

解析: 类指针的声明不会调用构造函数,但是指向一个类的实例(new)的时候会调用构造函数。类的声明会调用类的构造函数。

    TestClass p1,*p2;     //只会为p1调用默认构造函数

            p2=new TestClass ('X');       //为p2调用构造函数

    delete p2;             //释放p2指向的内存空间,为p2指向的实例调用析构函数

    return 0;              //程序结束,调用析构函数释放p1指向的内存空间

           最后输出AXBB。

13、关于下列程序,说法正确的是

void   fun()
{char b[2]={0};strcpy(b,"aaaa");
}
A:Debug版本崩溃,Release版本正常                              B:Debug版本正常,Release版本崩溃

C:  Debug版本崩溃,Release版本崩溃                              D:  Debug版本正常,Release版本正常       

解析:在Debug模式中,会有assert断言保护,所以会崩溃。而在Release模式中,会删掉assert断言保护,所以会正常运行。但是我在VS2010下运行两个版本都正常运行了......这就尴尬了....但是这两种模式的区别还是要知道的。

14、已知下列的class层次,其中的每一个类都定义有一个default constructor和一个virtual destructor,则下面执行dynamic_cast会失败的是()

class X{...};class A{...};class B:public A{...};class C:public B{...};class D:public X,public C{...};
A:  A *pa=new D;  X *px=dynamic_cast<X*>(pa)                        B:  D *pd=new D;  A *pa=dynamic_cast<A*>(pd)

C:  B *pb=new B;  D *pd=dynamic_cast<D*>(pb)                     D:  A *pa=new C;  C *pc=dynamic_cast<C*>(pa)
解析:dynamic_cast<>用于C++类继承多态间的转换,分为子类向基类的向上转换和基类向子类的向下转换。其中,子类向基类的向上转换不需要借助任何其他特殊的方法,只需要将子类的指针或者引用赋给基类的指针或者引用即可。而向下转换时要特别注意,dynamic_cast<>操作符安全的将基类类型的引用或者指针转换为派生类的引用或者指针,dynamic_cast再将基类cast到子类的时候,基类必须有虚函数,因为dynamic_cast运行时需要检查RTTI信息,只有带虚函数的类运行时才会检查RTTI。

           例:假如继承关系如下:C继承B,B继承A

  则:A *a=new B;   //new了一个B,向上转换为A,但是其本质还是B

  B *b=dynamic_cast<B *> a;     //把基类A向下转换为子类B,因为a的本质还是B,所以把B转换为B正确

  C *c=dynamic_cast<C*>a;     //把基类A向下转换为子类C,因为a的本质是B,而C是B的子类,把本质是B的东西转换为子类C,所以是错误的。

  由上可知,本题答案为C。

15.以下代码输出是什么?

int a=1,b=32;
printf("%d,%d",a<<b,1<<32);
解析:这里考虑的是左移里一个比较特殊的情况,就是 当左移的位数超过该数值类型的最大位数时,编译器会用左移的位数去模类型的最大位数,然后按余数进行移位。

    所以a<<b  <==>  b为32超过最大位数32,所以有效移位数为b%32=0,也就是左移0位还是其本身,1

    而对于1<<32,会直接进行移位,有效移位数就是32,移位后为0。

            参考:http://blog.csdn.net/chen825919148/article/details/8049069

      但是这个问题真正具体的话,在不同的编译器里会有不同的结果。

16、开发c代码时,经常见到如下类型的结构体定义:

typedef struct list_t
{struct list_t *next;struct list_t *prev;char data[0];
}list_t;
则,最后一行char data [0]的作用是:

 A :方便管理内存缓冲区     B:减少内存碎片化    C:标示结构体结束     D:没有作用

解析:最后的char data [ 0 ]是一个柔性数组,只能放在结构体的末尾,是声明一个长度为0的数组,就可以使得这个结构体是变长的。对于编译器来说,此时长度为0并不占用空间,因为数组名本身不占空间,它只是一个偏移量,数组名这个符号本身代表了一个不可修改的地址常量,是紧跟在结构体后面的地址,对于这个数组的大小,可以进行动态分配内存,以使得整个结构体的大小是可变的,而且编译器会支持对于数组data的越界访问,这种声明方法可以很巧妙地实现数组扩展。它的作用其实就是方便管理内存缓冲区,减少内存碎片化,而不是标示结构体的结束。
17、下面程序段包含了四个函数,其中具有隐含this指针的是

int f1();
class T
{
public :static int f2();
private:friend int f3();
protected:int f4();
};
解析: 只有非静态类成员才有this指针。友元函数不是类成员函数,所以没有this指针。
18、下列重载乘法运算符的函数原型声明中正确的是()

A:MyClass operator *(double ,MyClass)                  B:MyClass operator *(MyClass ,MyClass)

C:MyClass operator *(double ,double)                    D:MyClass operator *(MyClass ,double)

解析:C++中规定,重载运算符必须和用户自己定义的数据类型的对象一起使用。所以ABD

19、类A是类B的友元,类C是类A的公有派生类,忽略特殊情况,下列说法正确的是()

A: 类B是类A的友元         B:类C不是类B的友元            C:类C是类B的友元           D:类B不是类A的友元

解析:友元关系是单向的,不对称,不可继承。所以BD正确

20、下面程序的输出结果是

#include<iostream>
using namespace std;class A
{public :A(char *s){cout<<s<<endl;}~A(){}
};class B:virtual public A
{public:B(char *s1,char *s2):A(s1){cout<<s2<<endl;}
};class C:virtual public A
{public:C(char *s1,char *s2):A(s1){cout<<s2<<endl;}
};
class D :public B,public C
{public:D(char *s1,char *s2,char *s3,char *s4):B(s1,s2),C(s1,s3),A(s1){cout<<s4<<endl;}
};
int main()
{D *p=new D("class A","class B","class C","class D");delete p;return 0;
}
解析:最后的输出结果为class A,class B,class C,class D。虚继承D中只会包含一个A的组件, C++在基类是虚的的时,禁止信息通过中间类自动的传递给基类,必须通过初始化列表显式调用基类的构造函数,因此,D的构造函数中初始化列表显式调用A、B、C类的构造函数,但是B、C类构造函数中包含的对A的构造不影响D类对A的构造,也就是说如果D的构造函数改为D(char *s1,char *s2,char *s3,char *s4):B(s1,s2),C(s1,s3), A(s2) ,则会以s2的内容对A进行构造。  另外, 派生类构造函数执行的次序:先构造继承过来的父类,然后同级按顺序构造。

21、下列程序输出结果是什么

int main()
{bool first=true;int sum=0;int value;unsigned short i=0xFFFF;for(;i>=0;--i)   //<span style="color:#006600;">i是一个无符号整数,所以不能表示负数,当i等于0时,--i的下一个值还是0xFFFF,而不是-1,所以这里是一个死循环</span>{if(first){value=65536;sum+=value%3;first=false;}else{sum+=--value%3;    //这里优先级顺序是先自减再取余if(value<=0){cout<<sum<<","<<i;break;}}}return 0;
}
解析:输出结果:65536,65535。找到规律即可,注意一点就是 i是一个无符号整数,所以不能表示负数,当i等于0时,--i的下一个值还是0xFFFF,而不是-1。

22、下列说法正确的是:

A:一个空类默认一定生成构造函数,拷贝构造函数,赋值运算符,引用操作符,析构函数

B:可以有多个析构函数

C:析构函数可以为virtual,可以被重载

D:类的构造函数如果都不是public,则类的实例无法被创建。

解析:B:一个类有多个析构函数的话会对同一块内存多次释放。

            C:析构函数可以为virtual,但是不能够被重载,因为析构函数没有参数列表,但是可以被重写,例如在派生类中重新定义析构函数

            D:单例模式下,构造函数私有化,但是仍然可以实例化对象。

23、关于纯虚函数的说法,正确的是:

A:声明纯虚函数的类不能被实例化

B:声明纯虚函数的类成为虚基类

C:子类必须实现基类的*****

D:纯虚函数必须是空函数

解析:声明纯虚函数的类是抽象类,抽象类不能被实例化,基类被虚继承才是虚基类

24、以下不是double compare(int ,int )的重载函数的是:

A:int compare(double ,double )                             B:double compare(double,double )

C:double compare(double,int )                             D:int compare(int ,int )

解析:重载函数区别在于参数个数不一样或者参数类型不一样,与返回值类型无关。

25、在32位编译器下sizeof(p)为()

class P
{
private:int ival;
public:P();~P();int GetVal(){return ival;}virtual int SetVal(int val){ival=val;}
};
解析: 1、类的大小为类的非静态成员数据的类型大小之和,也就是说静态类成员数据不做考虑

            2、普通成员函数与类的sizeof()无关

            3、虚函数由于要维护虚函数表所以要占据一个指针的大小,也就是4字节

            4、类的总大小也要遵守字节对齐原则

    本题,4+4=8字节

26、以下关于指针的说法,正确的是()

A:int *const p与int const *p等价

B:const int *p与int * const p等价

C:const int *p与int const *p等价

D:int *p[10] 与 int (*p) [ 10 ] 等价

解析:C,都是指向一个整型常量的指针。

27、下列程序的运行结果是:

class B0
{
public:virtual void display(){cout<<"B0::display"<<endl;}
};
class B1:public B0
{
public:void display(){cout<<"B1::display"<<endl;}
};
class D1:public B1
{
public:void display(){cout<<"D1::diasplay"<<endl;}
};
void fun(<span style="color:#ff0000;">B0 ptr</span>)   //普通函数
{ptr.display();
}int main()
{B0 b0;B1 b1;D1 d1;fun(b0);fun(b1);fun(d1);return 0;
}
解析:注意到fun()的参数不是指针,也不是引用,所以会传递实参的副本,并把副本转化为B0类型,所以调用哪个版本的函数在编译时就已经确定。如果fun()的参数是指针或者引用就可以实现多态。
28、关于以下代码中的变量在内存中的存储位置描述不正确的是()

int a=0;
class someClass
{int b;static int c;
};int main()
{int d=0;someClass *p=new someClass();return 0;
}
A:b存在堆区      B:c存在堆区          C:d存在栈区          D:a存在全局变量区

解析:栈区:由编译器自动分配释放,存储为函数运行而分配的局部变量、函数参数、返回数据、返回地址等

            堆区:有程序员分配释放,new malloc之类的,如果程序员不释放,程序运行结束时由操作系统回收

            全局区:存放全局变量、静态数据、常量,程序结束后由系统释放

           文字常量区:存放常量字符串,程序结束后由系统释放

   程序代码区:存放函数体的二进制代码
           a:全局变量,存在全局变量区      b:成员变量,存放在堆区      c:静态成员变量,存放在全局区     d:局部变量,存放在栈区    p:方法变量,p本身存在栈区,但是指               向堆区内存空间

29、下面程序的输出结果是:

int main()
{int n[ ][3]={10,20,30,40,50,60};int (*p)[3];p=n;cout<<p[0][0]<<","<<*(p[0]+1)<<","<<(*p)[2]<<endl;return 0;
}
解析:p是一个数组指针,指向有3个int类型的一维数组。 p[0]表示第一行的地址,(*p)表示第一行。所以最后输出10,20,30

30、编译和执行下列c语言代码,输出结果是:

int main()
{char c='0';printf("%d  %d",sizeof(c),sizeof('0'));return 0;
}
解析:C语言:char a='0'    sizeof(a)=1     sizeof('0')=4       原因: C语言把 '0' 称为整形字符常量,被看成int类型,所以在32位机器上占4字节

    C++:char a='0'        sizeof(a)=1     sizeof('0')=1      原因:C++把‘0‘称为字符字面常量,被看成是char类型,所以占1字节
31、不考虑任何编译器优化,下列代码第10行会发生

# include<iostream>    //1
class B                //2
{                      //3};                     //4
B func(const B &rhs)   //5
{                      return rhs;        //6
}                      //7
int main()             //8        
{B b1,b2;           //9b2=func(b1);       //10
}
解析:一次拷贝构造函数发生在func函数执行完成,返回B类型的对象时,如果返回的是引用类型,则不会调用拷贝构造函数。因为返回的不是引用,所以将生成一个对象temp,将要返回的对象通过拷贝构造函数赋给它

            赋值运算符发生在将temp赋值给b1。

            最后将临时对象temp进行析构。
32、执行int x=1 ,int y=~x语句后,y的值为:

解析: 1的原码:0000 0000 0000 0000 0000 0000 0000 0001    补码:0000 0000 0000 0000 0000 0000 0000 0001

             ~1:  1111 1111 1111 1111 1111 1111 1111 1110 得到的是真值的补码表示,转换为真值的原码:1000 0000 0000 0000 0000 0000 0000 0010,即-2.

33、头文件已经正常包含,一下代码在vs上编译和运行的结果是:

class A 
{public:void test(){printf("test A");}
};
int main()
{A *pA =NULL;pA->test();
}
解析: 对于非虚成员函数,C++是静态绑定的,在编译时就已经确定了,即使pA为NULL,但是已经声明了类型就知道pA有个test函数,且test函数里没有用到成员变量,单单有个打印语句是可以运行成功的。
34、C++中,32位单精度浮点数能表示的十进制有效数字是多少位?

解析:单精度浮点数的有效位数是7位,双精度浮点型的有效位数是16位。

35、下列关于宏的描述,不正确的是()

A:宏会带来性能的缺失         B:宏不进行类型检查        C:宏可以做到函数无法做到的功能            D:编译时宏的处理早于函数

解析:宏只是预定义的函数,在编译阶段不进行类型安全性检查,在编译的时候将对应函数宏宏命令代替,对程序性能无影响。但是,宏为什么可以做到函数无法做到的功能呢?????????????

36、下列关于一个类的静态成员描述不正确的是()

A:静态成员变量可以被该类的所有方法访问                               B:该类的静态方法只能访问该类的静态成员函数

C:该类的静态数据成员变量的值不可修改                                   D:子类可以访问父类的静态成员

E:静态成员无多态特性

解析:类的静态成员属于整个类而不是某个对象,可以被类的所有方法访问,子类也可以访问父类的静态成员

            静态方法属于整个类,在对象创建之前就已经分配空间,类的非静态成员要在对象创建之后才有内存,所有静态方法只能访问静态成员不能访问非静态成员

            静态成员可以被任一方法修改,修改后的值可以被所有对象共享

            所以,C错误。

37、以下程序的运行结果是:

int *pint=0;
pint+=6;
cout<<pint<<endl;
解析:程序定义了一个指针,该指针指向地址为0的位置,然后向后移6个int大小的字节,所以输出24.

38、

#program pack(2)
class bu
{int number;union Ubffer{char [13];int number;}ubuf;void foo();typedef char *(*f)(void *);enum{hdd,ssd,blueray} disk;
}bu;
则sizeof(bu)的值为

解析:#program pack(2)
class bu
{
int number;                                 //4
union Ubffer                  
{
char [13];                           //13
int number;                       //4
}ubuf;                                          //union取最大为13,#program pack(2)为14。如果没有#program pack(2),则为16
void foo();                                      // 0
typedef char *(*f)(void *);            //0
enum{hdd,ssd,blueray} disk;    //4
}bu;

所以4+14+0+0+4=22

39、下面哪一个不是动态链接库的优点?

A:共享                B:装载速度快              C:开发模式好                  D:减少页面交换

解析:静态链接库的优点:代码转载速度快,执行速度略比动态链接库快;只需保证在开发者的计算机中有正确的.lib文件,在以二进制形式发布时,不需要考虑在用户的计算                                                   机上是否存在.lib文件及版本问题,可以避免dll炼狱等问题。

           动态链接库的优点:更加节省内存并减少页面交换;提高程序可维护性和可扩展性;共享

40、int a=5,则++(a++)的值是()

解析:++是一目运算符,只能用于变量,不能用于表达式,而(a++)是表达式,所以会编译错误。

41、以下程序的输出结果是:

#include <stdio.h> main()
{char a[10]={ '1','2','3','4','5','6','7','8','9',0},*p; int i;i=8;p=a+i;printf("%s\n",p-3); 
}
解析:p指向5, %s的输出直到遇到'\0'为止,但是0不是‘\0’,0只是表示一个空字符,所以最后的输出结果为6789.

42、声明语句是int a[3][4],下列表达式与a[2][1]等价的是()

A:*(a[2]+1)              B :a[9]                 C:*(a[1] +2)                    D:*(*(a+2))+1

解析:对于 a[3][4],a是一个指针数组,大小为3,里面三个元素就是该二维数组的每一行第一个元素的地址。

           1、*(a[2]+1),   a[2]就是第三行首元素的地址,a[2]+1 则地址向右偏移1,*(a[2]+1)就是取该地址的元素,也就是a[2][1]
           2、*(*(a+2)+1), *(a+2) 和a[2]是等价的。所以*(*(a+2)+1)也是表示a[2][1]
43、下列程序编译时会出现错误,请根据行号选择错误位置( )
#include <iostream>
using namespace std;
class A{int a1;
protected:int a2;
public:int a3;
};
class B: public A{int b1;
protected:int b2;
public:int b3;
};
class C:private B{int c1;
protected:int c2;
public:int c3;
};
int main(){B obb;C obc;cout<<obb.a1;//1cout<<obb.a2;//2cout<<obb.a3;//3cout<<obc.b1;//4cout<<obc.b2;//5cout<<obc.b3;//6cout<<obc.c3;//7return 0;
}
解析:三种继承方式:
            使用private继承,父类的protected和public属性在子类中变为private;
           使用protected继承,父类的protected和public属性在子类中变为protected;
           使用public继承,父类中的protected和public属性不发生改变; 

           所以,1.2.4.5.6.都有问题
44、经过表达式a=5?0:1后的a的值为:
解析:其实是这样的:a=(5?0:1),所以最后a的值为0.

45、执行下面语句后的输出是()

int I=1;
if(I<=0)printf("****\n");
elseprintf("%%%%\n");
解析:在 printf中%做为转义字符,两个%才相当于一个%,所以第一句输出****,第二句输出%%。

46、关于子类型的描述中,错误的是()

A:在公有继承下,派生类是基类的子类型

B:子类型的关系是不可逆的

C:子类型就是指派生类是基类的子类型

D:一种类型当他至少提供了另一种类型的行为,则这种类型是另一种类型的子类型。

解析:子类型必须是子类继承了父类的左右可继承的属性,也就是公有继承,才能收拾子类型,否则只能说是单纯的子类。

47、下列程序的输出结果是

void f()
{static int i=15;i++;cout<<"i="<<i<<endl;
}int main()
{for(int k=0;k<2;k++){f();}cin.get();return 0;
}
解析: static修饰的变量只初始化一次,当下次执行到初始化语句时,直接跳过。所以输出16,17

48、下列关于重载函数的描述中,错误的是()

A::重载函数中不允许使用默认参数

B:重载函数编译时根据参数表进行选择

C:构造函数重载将会给初始化带来多种方式

D:不要使用重载函数来描述毫无相干的函数

解析:重载函数中允许使用默认参数,但是要注意重载函数使的二义性,例如  int a(int ,int x=0)和int  b(int)
49、

C++支持函数的嵌套调用,但不支持函数的嵌套定义

50、下列哪个操作符不能被重载?

A:,(逗号)      B:()    C:.(点)      D:[ ]         E:->

解析:C++中不能重载的运算符包括: 点,::,?:.*四个。

             重载逗号运算符例子:http://blog.csdn.net/shanno/article/details/7387973

51、32位系统中,定义**a[3][4],则变量占用的内存空间为()

解析:a是一个数组,数组大小3*4,数组中存放着指针的指针,32位系统下,指针大小为4,所以4*3*4=48.

52、关于int *p,下列说法那些可能是正确的()

A:p是一个执行int型变量的指针

B:p是一个指向一维数组的指针

C:p是一个指向二维数组的指针

D:p是一个动态数组

解析:。。。。

53、下面函数的时间复杂度是

long foo(long x){if(x<2) return -1return x*x*foo(x-1);}
解析: 递归的时间复杂度:递归次数        空间复杂度:递归深度,也就是调用栈帧。

54、

这篇关于C++易错总结(持续更新)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/970729

相关文章

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

Linux Mint Xia 22.1重磅发布: 重要更新一览

《LinuxMintXia22.1重磅发布:重要更新一览》Beta版LinuxMint“Xia”22.1发布,新版本基于Ubuntu24.04,内核版本为Linux6.8,这... linux Mint 22.1「Xia」正式发布啦!这次更新带来了诸多优化和改进,进一步巩固了 Mint 在 Linux 桌面

Python中实现进度条的多种方法总结

《Python中实现进度条的多种方法总结》在Python编程中,进度条是一个非常有用的功能,它能让用户直观地了解任务的进度,提升用户体验,本文将介绍几种在Python中实现进度条的常用方法,并通过代码... 目录一、简单的打印方式二、使用tqdm库三、使用alive-progress库四、使用progres

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Ubuntu 24.04 LTS怎么关闭 Ubuntu Pro 更新提示弹窗?

《Ubuntu24.04LTS怎么关闭UbuntuPro更新提示弹窗?》Ubuntu每次开机都会弹窗提示安全更新,设置里最多只能取消自动下载,自动更新,但无法做到直接让自动更新的弹窗不出现,... 如果你正在使用 Ubuntu 24.04 LTS,可能会注意到——在使用「软件更新器」或运行 APT 命令时,

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

Java向kettle8.0传递参数的方式总结

《Java向kettle8.0传递参数的方式总结》介绍了如何在Kettle中传递参数到转换和作业中,包括设置全局properties、使用TransMeta和JobMeta的parameterValu... 目录1.传递参数到转换中2.传递参数到作业中总结1.传递参数到转换中1.1. 通过设置Trans的