您的位置:首页 > 其它

牛客刷题:笔试常考题和易错题(长期更新)

2017-05-22 17:38 429 查看
1,C++中为什么用模板类的原因?(即模板类的优点)

(1)可用来创建动态增长和减小的数据结构

(2)它是与类型无关的,因此具有很高的可复用性

(3)它在编译时而不是在运行时检查数据类型,保证了类型安全

(4)它是与平台无关的,有很强的可移植性

(5)可用于基本数据类型

2,以下程序的输出结果是什么?

int main()
{
int a = 1, b = 2, c = 3, d = 0;
if (a == 1 && b++ == 2)
{
if (b != 2 || c-- != 3)
{
cout << a << " " << b << " " << c << endl;
}
else
{
cout << a << " " << b << " " << c << endl;
}
}
else
{
cout << a << " " << b << " " << c << endl;
}
system("pause\n");
return 0;
}


这道题中与两点需要注意,(1)后置++是先使用再++;(2)||运算和&&运算的短路问题,||:当第一个条件为真时,则后面条件不执行。&&:当第一个条件不成立时,则后面的都不执行。因此,这道题第二个if语句,结果是1 3 3

3,以下代码中,a和b的地址相同吗,为什么?p1和p2地址相同吗,为什么?

int main()
{
int a = 1, b = 2, c = 3, d = 0;
if (a == 1 && b++ == 2)
{
if (b != 2 || c-- != 3)
{
cout << a << " " << b << " " << c << endl;
}
else
{
cout << a << " " << b << " " << c << endl;
}
}
else
{
cout << a << " " << b << " " << c << endl;
}
system("pause\n");
return 0;
}


大家先看调试结果



a和b地址不同,p1和p2地址相同,原因是a和b是在栈空间的两个字符数组,地址不同,p1和p2指向的位置在常量区,值都是abcde,所以是同一常量,地址相同。

4,若Myclass是一个类名,则如下语句中调用构造函数的个数是?

Myclass c1,*c2;
Myclass *c3 = new Myclass;
Myclass &c4 = c1;


c1调用一次构造函数,c2是一个指针,用来动态描述对象,不会调用类的构造函数,c3的右边新创建一个对象会调用构造函数,但是注意,这里的赋值运算符不是类中的赋值运算符,而是普通的赋值运算符。c4是一个对象引用,是c1的一个别名,所以不会调用构造函数。

5,传地址或引用时,形参与实参都有相同的地址,传值调用时,只是将数据进行了复制,不会改变实参的值。

6,以下代码,sizeof(list_t) = ?

tyedef struct list_t
{
struct list_t *next;
struct list_t *prev;
char data[0];//柔性数组
}list_t;


柔性数组,把单一元素的数组放在一个struct的尾端,使得每个struct对象可以拥有可变大小的数组,柔性数组不占空间,只是作为一个符号地址存在。所以,sizeof(list_t) = 8

7,在C++中,下面代码的执行结果是?

int main()
{
const int i = 0;
int *j = (int *)&i;
*j = 1;
printf("%d,%d",i,j);
system("pause\n");
return 0;
}


这段代码在C++中的结果是0,1;在C语言中的结果是1,1;原因如下:

C语言中的const是运行时const,编译时只是定义。

而C++中,const变量是编译时的常量,可以像#define定义的常量一样使用,故C++中,const变量额值在编译时就已经确定了,直接对const变量进行了值的替换。

8,下面代码的输出结果是什么?

int main()
{
int a[3];
a[0] = 0, a[1] = 1, a[2] = 2;
int *p, *q;
p = a;
q = &a[2];
cout << a[q - p] << endl;
system("pause\n");
return 0;
}


指针间相减是其地址空间的距离,我用图来解释这道题:



9,C++中,为了让某个类只能通过new来创建(即如果直接创建对象,编译器会报错),应该(将析构函数设为私有)。

编译器在为类对象分配栈空间时,会先检查类的析构函数的访问属性,其实不光是析构函数,只要是非静态的函数,编译器就会进行检查,如果类的析构函数是私有的,则编译器不会在栈上为类对象分配内存,因此,将析构函数设为私有,类对象就无法建立在栈(静态)上了,只能在堆上(动态new)分配类对象。

10,来看以下代码

class A
{
public:
virtual void print()
{
cout << "A::print()" << endl;
}
};

class C :public A
{
public:
virtual void print()
{
cout << "C::print()" << endl;
}
};

class B :public A
{
public:
virtual void print()
{
cout << "B::print()" << endl;
}
};

void print(A a)
{
a.print();
}

int main()
{
A a, *aa, *ab, *ac;
B b;
C c;
aa = &a;
ab = &b;
ac = &c;
a.print();
b.print();
c.print();
aa->print();
ab->print();
ac->print();
print(a);
print(b);
print(c);
system("pause\n");
return 0;
}


输出结果与分析如下



11,请分析以下代码的输出结果

void f(char* x)
{
x++;
*x = 'a';
}

int main()
{
char str[sizeof("hello")];
strcpy(str, "hello");
f(str);
cout << str<< endl;
system("pause\n");
return 0;
}


输出结果为hallo,f函数的作用是将字符串第二个字符替换成a,由于函数是值传递,不影响指针指向,所以str指针还是从字符串开头开始的。

12,以下 代码的输出结果是?

static int a = 1;
void fun1()
{
a = 2;
}

void fun2()
{
int a = 3;
}

void fun3()
{
static int a = 4;
}

int main()
{
printf("%d", a);
fun1();
printf("%d", a);
fun2();
printf("%d", a);
fun3();
printf("%d\n", a);
system("pause\n");
return 0;
}


输出结果为1 2 2 2,通过分步调试可以看到每一个printf语句中的a地址都是全局变量a的地址。第一个printf输出全局变量a = 1,在调用fun1()时,全局变量a的值被修改为2,而调用其他函数时,a为每个函数的局部变量,出了其作用域即被销毁。因此printf输出的都是全局变量a的值。

13,关于PA、PB、PC的取值,以下说法正确的是?

class A
{
public:
virtual void FunTestA()
{}
};

class B
{
public:
virtual void FunTestB()
{}
};

class C :public B, public A
{
virtual void FunTestC()
{}
};

int main()
{
C c;
A* pA = &c;
B* pB = &c;
C* pC = &c;
system("pause");
return 0;
}


A,pA、pB、pC的取值相同

B,pC和pA不相同

C,pB和pB不相同

D,pC不等于pA,也不等于pB

正确答案选B



14,若已定义:int a[9],*p = a;并在以后的语句中未改变p的值,不能表示a[1]地址的表达式是:

A,++p

B,a+1

C,p+1

D,a++

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  牛客