2016/11/8 反思

以下部分题目及解析来自牛客网及牛友,侵删

ascii码表:

数字0---48
数字9---57

大写字母A---65
大写字母Z---90
小写字母a---97
小写字母z---122

空格---32
下列程序的输出结果:

#include <iostream>
using namespace std;
class A
{
public:
    void print()
    {
        cout << "A:print()";
    }
};
class B: private A
{
public:
    void print()
    {
        cout << "B:print()";
    }
};
class C: public B
{
public:
    void print()
    {
A:: print();
    }
};
int main()
{
    C b;
    b.print();
}

A:print()
B:print()
C:编译出错

选c,因为b从A为private继承,但是值得我注意的不是这里,是A::print();这个表达
以下代码中,A 的构造函数和析构函数分别执行了几次:      
A*pa=new A[10];
delete []pa;
正确答案: B   你的答案: B (正确)

11
1010
110
101

A*pa = new A[10];  调用new分配原始未类型化的内存,在分配的内存上运行构造函数,即运行10次构造函数,对新建的对象进行初始化构造,返回指向分配并构造好的对象的数组指针
delete []pa; 对数组中的10个对象分别运行析构函数,然后释放申请的空间
下面有关C++中为什么用模板类的原因,描述错误的是?
正确答案: C   你的答案: B (错误)

可用来创建动态增长和减小的数据结构
它是类型无关的,因此具有很高的可复用性
它运行时检查数据类型,保证了类型安全
它是平台无关的,可移植性

答:(1)可用来创建动态增长和减小的数据结构 (2)它是类型无关的,因此具有很高的可复用性。 (3)它在编译时而不是运行时检查数据类型,保证了类型安全 (4)它是平台无关的,可移植性 (5)可用于基本数据类型
代码执行后,a和b的值分别为?

class Test{
public:
    int a;
    int b;
    virtual void fun() {}
    Test(int temp1 = 0, int temp2 = 0)
    {
        a=temp1 ;
        b=temp2 ;
    }
    int getA()
    {
        return a;
    }
    int getB()
    {
        return b;
    }
};

int main()
{
    Test obj(5, 10);
    // Changing a and b
    int* pInt = (int*)&obj;
    *(pInt+0) = 100;  
    *(pInt+1) = 200;  
    cout << "a = " << obj.getA() << endl;
    cout << "b = " << obj.getB() << endl;
    return 0;
}
正确答案: A   你的答案: C (错误)

200 10
5 10
100 200
100 10

 这么需要考虑虚函数表,指向虚函数表的指针在32位系统下占用4个字节,其地址分布在整个类成员变量的地址的首部,接下来就是变量a的地址、b的地址。当将test对象obj赋给指向整型的pInt后,指针pInt指向了地址的首部也就是虚函数表指针,所以*(pInt+0)=100改变的是虚函数表的值,接下来*(pInt+1)=200改变的是变量a的值,变量b没有变换。

在这道题里,我对 Test obj(5, 10);的赋值产生了困惑
i的初始值为0i++在两个线程里面分别执行100次,能得到最大值是?,最小值是 ? 。
你的答案 (错误)

200,100

正确答案:2002
最大值200,最小值2i++只需要执行一条指令,并不能保证多个线程i++,操作同一个i,可以得到正确的结果。因为还有寄存器的因素,多个cpu对应多个寄存器。每次要先把i从内存复制到寄存器,然后++,然后再把i复制到内存中,这需要至少3步。从这个意义上讲,说i++是原子的并不对。
如此,假设两个线程的执行步骤如下:
1. 线程A执行第一次i++,取出内存中的i,值为0,存放到寄存器后执行加1,此时CPU1的寄存器中值为1,内存中为02. 线程B执行第一次i++,取出内存中的i,值为0,存放到寄存器后执行加1,此时CPU2的寄存器中值为1,内存中为03. 线程A继续执行完成第99i++,并把值放回内存,此时CPU1中寄存器的值为99,内存中为994. 线程B继续执行第一次i++,将其值放回内存,此时CPU1中的寄存器值为1,内存中为15. 线程A执行第100i++,将内存中的值取回CPU2的寄存器,并执行加1,此时CPU2的寄存器中的值为2,内存中为16. 线程B执行完所有操作,并将其放回内存,此时CPU1的寄存器值为100,内存中为1007. 线程A执行100次操作的最后一部分,将CPU2中的寄存器值放回内存,内存中值为28. 结束!
所以该题目便可以得出最终结果,最小值为2,最大值为200
当参数*x==1, *y==1, *z==1时,下列不可能是函数add的返回值的( )?
int add(int *x, int *y, int *z){
    *x += *x;
    *y += *x;
    *z += *y;
    return *z;
 }
4
5
6
7

选D,开始不知道啥意思,后经牛客网的大神指点才知道这题要考虑的是,xy,z三个参数是否指向同一地址(或者说调用该函数时是否实参相同),如:当a=b=c=1时,add(&a,&a,&a),add(&a,&b,&c)。
通过写程序测试得出结果,不可能得到答案7。
有以下5种情况

这里写图片描述

内存对齐规定:结构体的总大小为结构体最宽基本类型成员大小的整数倍
下面有关函数模板和类模板的说法正确的有?
正确答案: A B C D   你的答案: A C (错误)

函数模板的实例化是由编译程序在处理函数调用时自动完成的
类模板的实例化必须由程序员在程序中显式地指定
函数模板针对仅参数类型不同的函数
类模板针对仅数据成员和成员函数类型不同的类



让我们从故事中找答案:
   首先揭开谜底;满堂彩   A B C D
 1、概述:
   模板(Template)是一种强大的C++软件复用特性,通常有两种形式:函数模板和类模板。函数模板针对仅参数类型不同的函数(答案C ok);类模板针对仅数据成员和成员函数类型不同的类(答案D ok)。函数模板和类模板可以是程序员只需制定一个单独的代码段,就可表示一整套称为函数模板特化的相关(重载)函数或是表示一整套称为类模板特化的相关的类。这种技术称为泛型程序设计(generic programming)。
使用模板的好处在于,可以使程序员编写与类型无关的代码。


-----------------
模板是一个类家族的抽象,它只是对类的描述,编译程序不为类模板(包括成员函数定义)创建程序代码,但是通过对类模板的实例化可以生成一个具体的类以及该具体类的对象。
与函数模板不同的是:函数模板的实例化是由编译程序在处理函数调用时自动完成的(答案A正确),而类模板的实例化必须由程序员在程序中显式地指定(答案B正确)

this指针保证基类保护成员在子类中可以被访问 这句话对吗?
错
this只对本类的非静态成员有效
有如下程序段:

char ch=-1;
printf(“%02x,%02x”,ch,(unsigned char)ch);
则输出:
-1,-1
ff,ff
ffffffff,ff
ff,ffffffff
下列程序的输出结果为:
1
2
3
4
5
6
7
8
#include
void main()
{
       char* a[ ] = { "hello", "the", "world"};
       char** pa = a;
       pa++;
       cout<<*pa<<endl;
}
正确答案: B   你的答案: B (正确)

theworld
the
hello
hellotheword
添加笔记
收藏
纠错
本题知识点

C/C++  迅雷
参考解析 添加解析
6

推荐
一坨小tt头像一坨小tt
分析:a是指针的数组 
char** p = a; //char** p = &a[0] 
p++;//p是指针自增+4,而a中元素是指针,每个正好四个字节,因此p++后恰好p= &a[1] *p=a[1];输出"the",输出结果为B
下列程序执行后输出的结果是
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
using namespace std;

int f(int a)
{
    int b = 0;
    static int c = 3;
    a = c++, b++;
    return (a);
}
int main()
{
    int a = 2, i, k;
    for (i = 0; i < 2; i++)
        k = f(a++);
    printf(" % d\n", k);

    return 0;
}

正确答案: D   你的答案: D (正确)

3
0
5
4

选D,这道题目考察的是操作符的优先级,因为逗号表达式的优先级最低,所有先计算赋值操作符,再计算逗号操作符,如果将a = c++, b++写成
a = (c++, b++),则答案选B
当i=0时,a=2,执行f(a++)即f(2++),c的初始值为3,f(2)的返回结果为3,之后,c的值变为4;
当i=1时,c的值为4,f(2)的返回结果为4,之后,c的值变为5
有以下程序
#include <stdio.h>
#include <stdlib.h>
void fun ( int *pl,int *p2,int *s )
{
    s = (int*) malloc(sizeof(int));
    *s*pl + *(p2++ );
}
main( )
{
    int a [2] = {l,2},b [2] = {10,20},*s = a;
    fun (a,b,s); 
    printf ( "%d \n", *s);
}
程序运行后的输出结果是?
正确答案: C   你的答案: A (错误)

11
10
1
2

malloc返回了一个新的指针,s的值没变

http://www.nowcoder.com/test/question/done?tid=5938035&qid=4953#summary

若有以下程序段

char str[4][12]={"aa", "bbb", "cccc", "d"},*strp[4];
int i;
for(i=0;i<4;i++) 
    strp[i]=str[i];
不能正确引用字符串的选项是
str[0]
strp
strp[3]
* strp

strp代表数组 strp[4]的首地址,这个数组存储的值是指向每个字符串的指针
发表于 2015-06-11 13:03:57回复(0)
2

清秋冷
strp代表数组的首元素的地址,首元素为指向“aa”的指针,那么strp就是指向“aa”指针的指针,是一个二级指针

http://www.nowcoder.com/questionTerminal/5a6e0056f81648fe97f9a85462e256c6

以下选项中非法的C语言字符常量是?
正确答案: D   你的答案: A (错误)

'\007'
'\b'
'a'
'\09'
添加笔记
收藏
纠错
本题知识点

字符串  C/C++
参考解析 添加解析
38

推荐
小Coral石头头像小Coral石头
本题考查字符常量,字符常量是用单引号括起来的一个字符。例如:'a''=''+'等。转义字符是一种特殊的字符常量。转义字符以反斜线"\"开头,后跟一个或几个字符。D选项中'\09',\0表示后面的字符是八进制数。又出现9所以是非法的,故D选项正确。
c++中,声明const int i,是在哪个阶段做到 i只可读的?
正确答案: A   你的答案: C (错误)

编译
链接
运行
以上都不对
添加笔记
收藏
纠错
本题知识点

C/C++  腾讯
参考解析 添加解析
8

推荐
SUWENQING头像SUWENQING
const用来说明所定义的变量是只读的。 这些在编译期间完成,编译器可能使用常数直接替换掉对此变量的引用。
编辑于 2015-02-03 15:52:55 回复(0)
更多回答(4条)
0

huixieqingchun头像huixieqingchun
const说明变量是常量,常量存储在常量区,在编译时就直接将其替换成相应的引用。
在int b[ ][3] = {{1},{3,2},{4,5,6},{0}};中,sizeof(b) = ?
正确答案: D   你的答案: B (错误)

4
12
28
48
注意这个数组是int型不是char
使用 char* p = new char[100]申请一段内存,然后使用delete p释放,有什么问题?
正确答案: B   你的答案: C (错误)

会有内存泄露
不会有内存泄露,但不建议用
编译就会报错,必须使用delete []p;
编译没问题,运行会直接崩溃
添加笔记
求解答(13)
收藏
纠错
本题知识点

C/C++  人人网
共有12条讨论 添加解析
40

revoid头像revoid
当用delete来释放用new int[]申请的内存空间时,由于其为基本数据类型没有析构函数,所以使用deletedelete []相同,两者都会释放申请的内存空间,若是自定义的数据类型,有析构函数时,用new []申请的空间,必须要用delete []来释放,因为要delete []时会逐一调用对象数组的析构函数,然后释放空间
以下程序输出是____。
1
2
3
4
5
6
7
8
9
10
#include <iostream> 
using namespace std; 
int main(void) 
{ 
    const int a = 10; 
    int * p = (int *)(&a); 
    *p = 20; 
    cout<<"a = "<<a<<", *p = "<<*p<<endl; 
    return 0; 
} 
正确答案: D   你的答案: B (错误)

编译阶段报错运行阶段报错
a = 10, *p = 10
a = 20, *p = 20
a = 10, *p = 20
a = 20, *p = 10
添加笔记
收藏
纠错
本题知识点

C/C++
参考解析 添加解析
46

推荐
柠檬香草头像柠檬香草
因为a 和p都指向相同的内存地址,所以输出的前两个结果是相同的,但为啥相同的内存里的结果不相同么?--这就是常量折叠.
这个"常量折叠"是 就是在编译器进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。可以算作一种编译优化。
因为编译器在优化的过程中,会把碰见的const全部以内容替换掉(跟宏似的: #define pi 3.1415,用到pi时就用3.1415代替),这个出现在预编译阶段;但是在运行阶段,它的内存里存的东西确实改变了!!!
简单的说就是,当编译器处理const的时候,编译器会将其变成一个立即数。 

http://www.nowcoder.com/test/question/done?tid=5938378&qid=23339#summary

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值