C++题目(四)

来源:互联网 发布:理财软件哪个收益最高 编辑:程序博客网 时间:2024/05/22 13:51

盛大笔试:
1.求输出结果:

#include "iostream"#include "vector"using namespace std;int main(void){ vector<int>array; array.push_back(100); array.push_back(300); array.push_back(300); array.push_back(500); vector<int>::iterator itor; for(itor=array.begin();itor!=array.end();itor++) {  if(*itor==300)  {   itor = array.erase(itor);  } } for(itor=array.begin();itor!=array.end();itor++) {  cout<<*itor<<" "; } return 0;}


vector在erase之后,指向下一个元素的位置,其实进行erase操作时将后面所有元素都向前移动,迭代器位置没有移动。itor=array.erase(itor)  erase返回下一个元素的地址,相当于给itor一个新值。这里,第一个300被删除后,迭代器指向第二个300,然而随后就有itor++,就指向500了。

2、在win32平台下,以下哪种方式无法实现进程同步?A
A、Critical Section      B、Event      C、Mutex         D、Semaphore

3、按照升序排列的一组数据123456798,下面哪种排序法在空间和时间上最优?C
A、快速排序             B、冒泡排序             C、插入排序             D、堆排序

快排在基本有序的时候效率最低,为O(n2),冒泡一直是O(n2),插入排序在有序的时候最快,这个题目中只要比较9次,交换一次就完成了排序。最差的时候为逆序的时候。堆排序和归并排序相对来说很稳定。

4、TCP的关闭过程,说法正确的是(D)

A、TIME_WAIT状态称为MSL(Maximum Segment Lifetime)等待状态 (2MSL)
B、对一个established状态的TCP连接,在调用shutdown函数之前调用close接口,可以让主动调用的一方进入半关闭状态
C、主动发送FIN消息的连接端,收到对方回应ack之前不能发只能收,在收到对方回复ack之后不能发也不能收,进入CLOSING状态(进入TIME_WAIT)
D、在已经成功建立连接的TCP连接上,如果一端收到RST消息可以让TCP的连洁端绕过半关闭状态并允许丢失数据。

5、操作系统的一些特别端口要为特定的服务做预留,必须要root权限才能打开的端口描述正确的是(C)
A、端口号在64512-65535之间的端口
B、所有小于1024的每个端口
C、RFC标准文档中已经声明特定服务的相关端口,例如http服务的80端口,8080端口等
D、所有端口都可以不受权限限制打开
6、以下描述正确的是
A、虚函数是可以内联的,可以减少函数调用的开销提高效率
B、类里面可以同时存在函数名和参数都一样的虚函数和静态函数
C、父类的析构函数是非虚的,但是子类的析构函数是虚的,delete子类对象指针会调用父类的析构函数
D、以上都不对
C为对的,即使父类和子类都没有加上virtual,还是会照常调用父类的析构函数的。
A为正确的,可以参考:http://blog.csdn.net/zy1691/article/details/3606128

7、简答题:快速排序的思想是递归的,但是它的平均效率却是众多排序算法中最快的,为什么?
下面是我的理解,在网上也没有找到答案。
快排的递归的层次是有限的,如果每次的选取划分的元素都是中间值的话,那么规模下降是很快的。
主要同堆排序和归并排序相比,正是因为它的最坏可以到O(n2)的不稳定,平均性能才会超过它们的,堆排序和归并排序每次不管初始的数据是什么样子的,都需要O(nlog2n)的时间复杂度。而快排,在大多数一般的情况下,用到分而治之的思想,所以会很快。


搜狗笔试:
8、下面代码中for循环共执行了多少次?
unsigned short i,j; 
    for(i=0, j=2; i!=j; i+=5, j+=7) 
    {} 
short占用2个字节,当数据范围到头了(2^16-1),就又从0开始计数了,这个其实就是两辆汽车行驶在一个圆圈里的汽车追及问题。一个速度为5,一个速度为7,当速度为7的超越速度为5的时候,两个汽车就相遇了,2 + 7n - 5n = 2^16 所以共循环了32767次。

9、已知程序代码如下:
struct S
{
 void func1(S &);
 void func2(const S&);
 void func3(S&) const;
 void func4(const S&) const;
};
下面哪些能正常执行()

A、makeS().func1(makeS())

B、makeS().func2(makeS())

C、makeS().func3(makeS())

D、makeS().func4(makeS())

我在gcc上做的实验,这个结果和maskS()有关。首先
S makeS()
{
 S s;
 return s;
}
如果这样写的话,有1和3,不能正常运行,这个时候makeS返回的为一个临时的对象,如果func1(S&)这样试图对这个临时的对象进行改变是没有意义的,改变了对于程序员来说也是没有意义的。gcc的就编译不过去了,编译不过去的原因可能是试图寻找参数为非引用的函数,但是没有找到。如果改成了
S& makeS()
{
 S s;
 return s;
}
返回的为一个引用,这个时候编译器会警告我们,但是可以编译通过,四个函数都可以找到。还可以写成
S& makeS()
{
 S *s = new S;
 return *s;
}
这个时候编译器就啥也不说了。

10、下面程序应该输出多少?
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;
}
POINT
ER
ST
EW
关键是理解,数组的下标表示的真正的意义,是偏移-offset,a[i]对于编译器的意思是,取出符号a代表的地址,pa,在加上i*sizeof(a元素)的偏移量,最后解析出来对应的地址的内容。

11、下面哪个会使这段程序编译错误?

class A
{
public:
 A()
 {
 }
};
class B:public A
{
public:
 B()
 {
 }
};
A *pb = new B();
B b;

A、  A *pa = dynamic_cast<A *>(pb);

B、 A *pa = static_cast<A *>(pb);

C、 A a = static_cast<A >(b);

D、 A a = dynamic_cast<A >(b);

E、None of above

D 会使得编译错误,dnnamic_cast的参数必须为指针或引用。

A 只是把pb赋值给了pa,连类型都没有改变,其实直接等价于 pa = pb;

B  相当于强制类型转换,等价于 A *pa = (A*) pb;完全没有必要,因为pb就是A*类型的指针。

C  相当于A a =(A)b;强制类型转换,会发生截断的
dynamic_cast 的目标类型无效。C++primary上“dynamic_cast操作符将基类类型对象或引用转换为同一继承层次中其他类型的指针或者引用。与dynamic_cast一起使用的指针必须是有效的,它必须为0或者指向一个对象。与其他强制类型转换不同,dynamic_cast涉及运行时类型检查。如果绑定到引用或指针的对象不是目标类型的对象,则dynamic_cast失败。”dynamic_cast的转换目标是指针或引用,所以这编译会出错。
总感觉上面使用dynamic_cast有问题,没写一样,直接写A *pa = pb就可以了。dynamic_cast是将基类类型的对象指针(这一点符合),转换为同一继承层次中其他类型的指针(这个应该为继承类类型的一个指针,应该是B *pa = dynamic_cast<B *>(pb),但是如果是上述代码直接这样改了,还是不对,编译器会报错说类中没有多态,所以如果想真正dynamic(编译通过并且实现效果),必须是把基类类型的指针,转成派生类类型的指针,并且原来的基类类型的指针指向一个派生类对象,代码如下)。

#include <iostream>
using namespace std;

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

class B:public A{
        public:
                virtual int fun(){cout<<"B"<<endl;};
                void print(){cout<<"B::print"<<endl;};
                int get(){return 1;};
};

A *p = new B;
B b;

int main()
{
        p->print();
        p->fun();
        B *pb = dynamic_cast<B *>(p);
        pb->print();
        p->fun();
        return 0;
}
输出为:
A::print
B
B::print
B
虽然虚函数调用转化前一样,但是实际指向的对象的位置是改变了,以前指向派生类中基类的部分,转换后指向整个派生类。

12、如何用两个栈来实现一个队列,并分析有关队列操作的运行时间。


13、如何用两个队列实现一个栈,并分析有关栈操作的运行时间。

 

浙商银行
14、下面代码的输出是多少?
int main(void)
{
 FILE *fp;
 char str[100];
 fp=fopen("myfile.dat","w");
 fputs("abc",fp);
 fclose(fp);

 fp=fopen("myfile.data","a++");
 fprintf(fp,"%d",28);
 rewind(fp);
 fscanf(fp,"%s",str);
 puts(str);
 fclose(fp);

 return 0;
}

15、abstract class 和interface的区别?

完美世界:

16、下面程序的正确输出结果为()
class test
{
public:
 void print()
 {
  cout<<"test"<<endl;
 }
};

int main(void)
{
 test *t = new test();
 t->print();
 t = NULL;
 t->print();
 return 0;
}
A、编译不通过           B、运行时必然出错退出          C、运行时可能出错退出
D、test                    E、test  test                           F、test  随机信息 
print是一个类级别的东西(所有的类共有的一个东西),也就是说它和类的实例(或者类的对象)没有任何关系,这也就是说“并未使用this指针”,在这种情况下,print仅与test的类型有关,而不管t是什么东西,只要是类类型的指针就可以调用这个函数。
对象级别的东西,比如类中的某个非静态成员变量,这种东西和类的实例有关,因此它使用this指针。
其实静态成员变量也是类级别的东西,例子如下:
#include <iostream>
using namespace std;

class A
{
        public:
                void print(){cout<<n<<endl;};
                static int n;
};
int A::n = 1;

int main()
{
        A *a = new A;
        a->print();
        a = NULL;
        a->print();
        ((A *)0)->print();
        return 0;
}
上面三种都可以正常的输出。甚至可以直接构造一个指针。


迅雷:
17、某二叉树结点的中序序列为A、B、C、D、E、F、G,后序序列为B、D、C、A、F、G、E,该二叉树对应的树林包括多少棵树(B)
A、1    B、2    C、3     D、4

腾讯实习:
18、给定3个int类型的正整数x,y,z,对如下4组表达式判断正确的选项()
Int a1=x+y-z; int b1=x*y/z;
Int a2=x-z+y; int b2=x/z*y;
Int c1=x<<y>>z; int d1=x&y|z;
Int c2=x>>z<<y; int d2=x|z&y;

A、a1一定等于a2
B、b1一定定于b2
C、c1一定等于c2
D、d1一定等于d2

答案是A。虽然x+y可能溢出,但是即使溢出也是只丢失了一个符号位。那么A可以分两种情况,都是溢出的情况,不是溢出的情况值肯定一样。溢出假设x和y同号。情况一:如果x和y与z同号为正,x+y溢出,那么溢出后的值为最大的负数,在-z符号有一次改变。符号改变了两次,相当于最高位的值没有改变。而这个时候x-z+y因为同号也不可能符号改变,低位又都是直接相加,所以x-z+y与x+y-z一样。还有就是x和y与z不同号,这个时候就更容易了,x+y-z溢出,x-z+y同样溢出,符号位改变一次,所以也相等。情况二:其实和情况一一样x和y同号为负数。

其实对于计算机,任何两个数相加a+b(包括负数,-1-2在计算机看来就是-1+(-2),注意负数在计算机中存放的特殊性),在计算的时候是直接取出表示这个数字的字节,然后从低位到高位相加的,最后得出来一个结果,然后任你是有符号还是无符号都在把这个结果翻译成对应的数就好了。

19、程序的完整编译过程分为是:预处理,编译,汇编等,如下关于编译阶段的编译优化的说法中不正确的是()
A、死代码删除指的是编译过程直接抛弃掉被注释的代码;
B、函数内联可以避免函数调用中压栈和退栈的开销
C、For循环的循环控制变量通常很适合调度到寄存器访问
D、强度削弱是指执行时间较短的指令等价的替代执行时间较长的指令

答案:A
在大多数的机器上,调用函数都要做很多工作:调用前保存寄存器,并在返回时恢复;复制实参;程序还必须转向一个新位置执行。内联函数避免函数调用的开销。
所谓死代码就是其计算结果永远不会被使用的语句。
所谓强度削弱,就是用一种(或一串)执行时间较短的操作去等价地代替一个操作。例如,乘以2的n次方运算可以用左移来替换(例如,X*8可替换为X<<3),因为在多数机器上,左移运算的速度比乘法运算的速度快。


20、如下关于链接的说法错误的是(C)

A、一个静态库中不能包含两个同名全局函数的定义
B、一个动态库中不能包含两个同名全局函数的定义
C、如果两个静态库都包含一个同名全局函数,他们不能同时被链接
D、如果两个动态库都包含一个同名全局函数,他们不能同时被链接

(解答参考网络)函数可以定义在3个地方
1. 程序自身
2. 静态库
3. 动态库
因为静态库是要链进程序的,所以函数定义在程序和静态库可以看成是一样的
同名函数出现在程序和静态库中,链接时会报重定义的错误。
同名函数出现在动态库中,编译链接都可以通过,但是调用会出问题,会出现覆盖问题。

定义在这3个地方的函数,会调用哪个函数呢?

1. 程序和静态库定义了同名函数,链接报错:重定义
2. 程序或静态库定义的同名函数,会覆盖动态库中定义的函数
3. 动态库中定义的同名函数,先链接覆盖后链接的函数

 

参考:http://blog.csdn.net/hackbuteer1/article/details/7438986