int func(){char b[2] = {0};strcpy(b,"aaaa");}
以下说法哪个正确:
A Debug版崩溃,Release版正常
B Debug版正常,Release版崩溃
C Debug版崩溃,Release版崩溃
D Debug版正常,Release版正常
选A。因为在Debug中有ASSERT断言保护,所以要崩溃,而在Release中就会删掉ASSERT,所以会出现正常运行。但是不推荐如此做,因为这样会覆盖不属于自己的内存,这是搭上了程序崩溃的列车
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));
}
A bar1无法通过编译 B bar2无法通过编译
C bar3无法通过编译 D bar1可以正确运行,但是采用了错误的cast方法
选B。dynamic_cast是在运行时遍历继承树,所以,在编译时不会报错。但是因为A和B没啥关系,所以运行时报错,动态的,所以运行时转换(所以A和D都是错误的)。static_cast:静态的,编译时转换,编译器隐式执行的任何类型转换都可由它显示完成,如果两个类无关,则会出错(所以B正确),如果存在继承关系,则可以在基类和派生类之间进行任何转型,在编译期间不会出错。所以bar3可以通过编译(C选项是错误的)。
第十二题:下列哪些template实例化使用,会引起编译错误?
template
class stack;
void fi(stack); //A
class Ex
{
stack& rs; //B
stack si; //C
};
int main()
{
stack* sc; //D
fi(*sc); //E
int i = sizeof(stack); //F
return 0;
}
选C E F; 请注意stack和fi都只是声明不是定义。我还以为在此处申明后,会在其他地方定义呢,坑爹啊。
由于stack只是声明,所以C是错误的,stack不能定义对象。E也是一样,stack只是申明,所以不能执行拷贝构造函数,至于F,由于stack只是声明,不知道stack的大小,所以错误。如果stack定义了,将全是正确的。
#include<stdio.h>
#include<string>
#include<iostream>
using namespace std;
class A
{
public:
string a;
void f1(){printf("Hello World");}
void f2(){a = "Hello World"; printf("%s",a.c_str());}
virtual void f3(){printf("Hello World");}
virtual void f4(){a = "Hello World";printf("%s",a.c_str());}
static int i;
static void f5(){cout<<i<<endl;}
};
void main()
{
A* aptr = NULL;aptr->f1();
A* aptr = NULL;aptr->f2();
A* aptr = NULL;aptr->f3();
A* aptr = NULL;aptr->f4();
}
在Class A中没有写public,所以全是private,以至于f1,f2,f3,f4都将失败。如果改成PUBLIC那么:只有A正确,因为A没有使用任何成员变量,而成员函数是不属于对象的,所以A正确。其实,A* aptr = NULL;aptr->f5();也是正确的,因为静态成员也是不属于任何对象的。至于BCD,在B中使用了成员变量,而成员变量只能存在于对象,C有虚表指针,所以也只存在于对象中。D就更是一样了
在Inter CPU上,以下多线程对int型变量x的操作,哪几个不是原子操作,假定变量的地址都是对齐的。
A x = y B x++ C ++x D x=1
只有D选项才是原子操作
第八题:关于C++标准模板库,下列说法错误的有哪些:
A std::auto_ptr类型的对象,可以放到std::vector >容器中;
B std::shared_ptr类型的对象,可以放到std::vector >容器中;
C 对于复杂类型T的对象tObj,++tObj和tObj++的执行效率相比,前者更高
D 采用new操作符创建对象时,如果没有足够的内存空间而导致创建失败,则new操作符会返回NULL。
选择:A,D。A中auto是给别人东西而自己没有了(auto_ptr与boost库中的share_ptr不同的,auto_ptr没有考虑引用计数,因此一个对象只能由一个auto_ptr所拥有,在给其他auto_ptr赋值的时候,会转移这种拥有关系。)。所以不符合vector的要求。而B可以。C不解释。D选项在谭浩强的C++程序设计上说是正确的(谭浩强写书时可能是正确的,那时C++的新标准还没出来),但是实际上市错误的。因为:new操作符有三种,(1)plain new/delete就是operator new/delete。这种在为标准化时,C++中的new运算符总是返回NULL表示分配失败,就像malloc一样,因此程序员不得不检查其返回值。标准C++修订了new的语义,plain new在失败后抛出标准异常std::bad_alloc而不是返回NULL。然而,现在很多使用C++的程序员还以为new是以前的老样子,于是通过检查其返回值是否为NULL来判断分配成功与否,显然这是徒劳的;(2) nothrow new就是不抛出异常的运算符new的形式,nothrow new在失败时返回NULL,所以使用它就不需要设置异常处理器。而是像过去一样检查返回值是否为NULL即可。(3)placement new/delete:在指定的内存地址调用构造函数和析构函数,不会引起内存的分配。
#include<iostream>
#include<stdio.h>
using namespace std;
class A
{
public:
void foo(){}
};
class B:virtual public A
{
public:
void foo(){}
};
class C:virtual public A
{
public:
void foo(){}
};
class D: public B,public C
{
public:
void foo(){}
};
int main(int argc, char *argv[])
{
cout<<"A 的大小为: "<<sizeof(A)<<endl;
cout<<"B 的大小为: "<<sizeof(B)<<endl;
cout<<"C 的大小为: "<<sizeof(C)<<endl;
cout<<"D 的大小为: "<<sizeof(D)<<endl;
return 0;
}
输出1,4,4,8,空类只有一个字节,每一次虚继承都要保存一个基类的虚表地址
class A
{
public:
int b;
char c;
virtual void print()
{cout<<"this is a father‘s function!"<<endl;}
};
class B :public A
{
public:
virtual void print()
{cout<<"this is a children‘s function!"<<endl;}
};
int main()
{
cout<<sizeof(A)<<" "<<sizeof(B)<<endl;
return 0;
}
输出为12,12.如果把char c去掉,那么输出8,8,因为char由于字节对齐,所以原题需要12个字节。
子类继承父类的虚表并覆盖其中的条目。而且指向虚表的指针在每个类中也只有一个,如果子类是虚继承父类class B :virtual public A,那么子类比父类多4个字节
#include
using namespace std;
int main()
{
http://www.sogou.com
cout<<"welcome to sogou"<<endl;
return 0;
}
A:编译时;B:运行时;C:编译和运行时都出错;D程序运行正常
选D。因为http://www.sogou.com中//后面是注释,前面是标签(类似goto的标签)