C++小题(七)


/*
关于代码输出正确的结果是()
int main(int argc, char *argv[])
{
    string a="hello world";
    string b=a;
    if (a.c_str()==b.c_str())
    {
        cout<<"true"<<endl;
    }
    else cout<<"false"<<endl;
    string c=b;
    c="";
    if (a.c_str()==b.c_str())
    {
        cout<<"true"<<endl;
    }
    else cout<<"false"<<endl;
    a="";
    if (a.c_str()==b.c_str())
    {
        cout<<"true"<<endl;
    }
    else cout<<"false"<<endl;
    return 0;
}
正确答案: D   

A false false false
B true false false
C true true true
D true true false

三个if条件判断的都是a,b两个指针的值是否相同。
程序开始将a,b都指向了同一个字符串地址,这时两个指针的值相同,所以第一个输出true。
接着程序将c指向了b,又将c指向了一个空字符串。但是对a,b并没有影响,所以第二个输出还是true。
然后程序将a指向了一个空字符串空间,这时的a指针已经发生了变化,指向的不再是原来的“hello world ”而是新的一块空间。
因此这时的a,b指针的值不相等。这时输出false。所以答案选d,true true false
*/

/*
下列代码的输出为:
class CParent 
{
    public: virtual void Intro()
    {
        printf( "I'm a Parent, " ); Hobby();
    }
    virtual void Hobby()
    {
        printf( "I like football!" );
    }
}; 
class CChild : public CParent { 
    public: virtual void Intro()
    {
        printf( "I'm a Child, " ); Hobby();
    }
    virtual void Hobby()
    {
       printf( "I like basketball!\n" );
    }
}; 
int main( void )
{
    CChild *pChild = new CChild(); 
    CParent *pParent = (CParent *) pChild; 
    pParent->Intro(); 
    return(0);
}


正确答案: C   

A I'm a Parent, I like football!
B I'm a Parent, I like basketball!
C I'm a Child, I like basketball!
D I'm a Child, I like football!
*/

/*
说明一下++p 与 p++ 的区别。
正确答案: B   你的答案: B (正确)

A 没有区别
B ++p更好一些
C p++更好一些
D 和编译器有关
*/

/*
在32位系统环境,编辑选项为4字节对齐,那么sizeof(A)和sizeof(B)是____
struct A{
  int a;
  short b;
  int c;
  char d;
};
struct B{
  int a;
  short b;
  char d;
  int c;
};
正确答案: C   

A 16,16
B 13,12
C 16,12
D 11,16
按照下面3个条件来计算:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该基本数据类型所整除的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为上面介绍的对齐模数。
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
备注:为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员的整数倍,若是,则存放本成员,反之,则在本成员和上一个成员之间填充一定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节(trailing padding)。

A中,a占4个字节,b占1个字节,但因为c占4个字节,为了满足条件2,b需要占用4个字节,为了满足条件1,d需要占用4个字节,所以一共是16个字节;

B中,a占用4个字节,b占用2个字节,d占用1个字节,但因为c占用4个字节,为了满足条件2,d需要占用2个字节,即abd共占用8个字节,加上c的4个字节,一共12个字节;
*/

/*
以下程序
#include <stdio.h>
void fun( char ** p)
{
    int i;
    for(i=0;i<4;i + + )printf("% s",p[i]);
}
main( )
{
    char *s[6]={ "ABCD", "EFGH", "IJKL", "MNOP", "QRST", "UVWX" };
    fun(s);   
    printf("\n");
}
程序运行后的输出结果是?
正确答案: D   你的答案: D (正确)

A ABCDEFGHIJKL
B ABCD
C AEIM
D ABCDEFGHIJKLMNOP
s表示指向字符数组的指针,s指向了第一个字符串,s + +指向了第二个字符串,所以最后输出结果为D选项。
*/

/*
若char是一字节,int是4字节,指针类型是4字节,代码如下:

class CTest
{
    public:
        CTest():m_chData(‘\0’),m_nData(0)
        {
        }
        virtual void mem_fun(){}
    private:
        char m_chData;
        int m_nData;
        static char s_chData;
};
char CTest::s_chData=’\0’;
问:
(1)若按4字节对齐sizeof(CTest)的值是多少?
(2)若按1字节对齐sizeof(CTest)的值是多少?
请选择正确的答案。
正确答案: C   

A 16 4
B 16 10
C 12 9
D 10 10
*/

/*
请看一下这一段C++代码,如果编译后程序在windows下运行,则一下说话正确的是?
char*p1 = “123456”;
char*p2 = (char*)malloc(10);

正确答案: A C   

A p1 和 p2都存在栈中
B p2指向的10个字节内存在栈中
C 堆和栈在内存中的生长方向是相反的
D “123456”这6个字符存储在栈中

生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;
对于栈来讲,他的生长方向是向下的,是向着内存地址减小的方向增长。

一个由C/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其 
操作方式类似于数据结构中的栈。 
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回 
收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的 
全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另 
一块区域。 - 程序结束后由系统释放。 
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放 
5、程序代码区—存放函数体的二进制代码。
*/

/*
使用 char* p = new char[100]申请一段内存,然后使用delete p释放,有什么问题?
正确答案: B   

A会有内存泄露
B不会有内存泄露,但不建议用
C编译就会报错,必须使用delete []p;
D编译没问题,运行会直接崩溃

当用delete来释放用new int[]申请的内存空间时,由于其为基本数据类型没有析构函数,
所以使用delete与delete []相同,两者都会释放申请的内存空间,
若是自定义的数据类型,有析构函数时,用new []申请的空间,必须要用delete []来释放,
因为要delete []时会逐一调用对象数组的析构函数,然后释放空间
*/

/*
某32位系统下, C++程序,请计算sizeof 的值
char str[] = "http://www.xxxxx.com" 
char *p = str ;
int n = 10; 
请计算 
sizeof (str ) = 21
sizeof ( p ) = 4
sizeof ( n ) = 4
void Foo ( char str[100]){
请计算 sizeof( str ) = 4
} 
void *p = malloc( 100 ); 请计算 sizeof ( p ) = 4

*/

/*
假定变量I,f,d数据类型分别为int,float和double(int用补码表示,float和double分别用IEEE754单精度和双精度浮 点数据格式表示),
已知i=785,f=1.5678e^3,d=1.5e^100若在32位机器 中执行下列关系表达式,则结果为真是()
(I)i==(int)(float)I
(II)f==(float)(int)f    
(III)f==(float)(double) f    
(IV)(d+f)-d==f
正确答案: B   

仅I和II
仅I和III
仅II和III
仅III和IV
*/

/*
给定程序中,函数fun的功能是:将形参给定的字符串、整数、浮点数写到文本文件中,再用字符方式从此文本文件中逐个读入并显示在终端屏幕上。 
请在程序的下画线处填入正确的内容并把下画线删除,使程序得出正确的结果。 
试题程序:

void fun (char *s, int a, double f)
{

    1 * fp;
    char ch; &
    fp = fopen("filel.txt", "w");
    fprintf (fp, "% S % d %f\n", % '%', f);
    fclose(fp);
    fp = fopen("filel.txt", "r");
    printf("\nThe result:\n\n");
    ch = fgetc(fp);
    while (!feof ( 2 ))
    {

        putchar( 3 );
        ch = fgetc(fp);
        putchar('\n');    
    }
    fclose(fp);
}
int main( )
{
    char a[10] = "hello!"; 
    int b = 12345;
    double c = 98.76;
    fun(a, b, c);
}

你的答案 (正确)

1 FILE

2 fp

3 ch
*/

/*
 base_class bc;
cout << "base_class 的虚函数表首地址为:" << (int*)&bc << endl; // 虚函数表地址存在对象的前四个字节
*/

/*
已知int a[]={1,2,3,4,5};int*p[]={a,a+1,a+2,a+3};int **q=p;表达式*(p[0]+1)+**(q+2)的值是__2+3=5__。
*/

/*
在一个64位的操作系统中定义如下结构体:

struct st_task
{
    uint16_t id;
    uint32_t value;
    uint64_t timestamp;
};
同时定义fool函数如下:

void fool()
{
    st_task task = {};
    uint64_t a = 0x00010001;
    memcpy(&task, &a, sizeof(uint64_t));
    printf("%11u,%11u,%11u", task.id, task.value, task.timestamp);
}
上述fool()程序的执行结果为()
1 0 0
小端机器,字节对齐两个问题
   a:01 00 01 00 00 00 00 00
task:01 00 01 00 00 00 00 00
     id  丨pad  /value     /timestamp


*/

/*
对于下面的说法,正确的是____。
正确答案: F   

A对于 struct X { short s; int i; char c; },sizeof(X) 的值等于 sizeof(s) + sizeof(i) + sizeof(c)
B对于某个double变量 a,可以使用 a == 0.0 来判断其是否为零
C初始化方式 char a[14] = "Hello, world!"; 和初始化方式 char a[14]; a = "Hello, world!"; 的效果相同
D在gcc编译器下,对于 int i = 3; printf("%d %d", ++i, ++i),运行输出为:4 5
E选项A、B、C、D中至少有两个是正确的
F以上选项均不正确


编译器在编译程序时会遵循两条原则:
一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍) 
二、结构体大小必须是最大成员大小的整数倍
对于A,sizeof(X)=2+2+4+1+3=12
对于B,要判断一个双精度浮点数:if( abs(f) <= 1e-15 )
对于C,第二种初始化方式是错误的,无法通过编译
对于D,输出为5,5,	int i = 3; printf("%d %d", i, --i);输出2 2 由右向左计算,最后输出 
*/

/*
对于下面的代码,说法正确的是____。
char* s1 = "Hello world";
char s2[] = "Hello world";
s1[2] = 'E';     // 1
s2[2] = 'E';     // 2
*(s1 + 2) = 'E';  // 3
*(s2 + 2) = 'E';  // 4

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

A语句2、4是非法的
B语句3、4是非法的
C语句1、3是非法的
D仅语句1是非法的
E仅语句2是非法的
F语句1~4都是合法的

s1存储在常量区,1和3都是非法的
严格来说赋值语句应该是 const char* s1 = "Hello world"。
*/ 

/*
下面有关c++线程安全,说法错误的是?
正确答案: C   你的答案: C (正确)

A 线程安全问题都是由全局变量及静态变量引起的
B 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全
C c++标准库里面的string保证是线程安全的
D POSIX线程标准要求C标准库中的大多数函数具备线程安全性

1.局部变量局部使用是安全的 
为什么?因为每个thread 都有自己的运行堆栈,而局部变量是生存在堆栈中,大家不干扰。
2.全局原生变量多线程读写是不安全的  , 全局变量是在堆(heap)中。
3.函数静态变量多线程读写也是不安全的。
4.volatile能保证全局整形变量是多线程安全的么? 
不能。 volatile仅仅是告诫compiler不要对这个变量作优化,每次都要从memory取数值,而不是从register
5.InterlockedIncrement保证整型变量自增的原子性
写好多线程安全的法宝就是封装,使数据有保护的被访问到 
安全性:

局部变量 > 成员变量 > 全局变量 
*/

/*
有一个类B继承自类A,他们数据成员如下:
class A {
...
private:
   int &a;
};
class B : public A {
...
private:
     int a;
public:
     const int b;
     A c;
     static const char* d;
     A* e;
};
则构造函数中,成员变量一定要通过初始化列表来初始化的是____。
正确答案: A   你的答案: A (正确)
b c
b c e
b c d e
c e
b d
b e
常量成员和引用成员自然是要初始化的,问题就在这static成员。
static成员是不允许在类内初始化的,除了const,那么static const 成员是不是在初始化列表中呢?
答案是NO
一是static属于类,它在未实例化的时候就已经存在了,而构造函数的初始化列表嘞,只有在实例化的时候才执行。
二是static成员不属于对象。我们在调用构造函数自然是创建对象,一个跟对象没直接关系的成员要它做什么呢
c需要初始化不是因为它是类对象,是因为他的成员有引用。
*/ 

/*
class Test
{
    public:
        ____ int a;
        ____ int b;
    public:
        Test::Test(int _a , int _b) : a( _a )
        {
             b = _b;
        }
};
int Test::b;
int main(void)
{
    Test t1(0 , 0) , t2(1 , 1);
    t1.b = 10;
    t2.b = 20;
    printf("%u %u %u %u",t1.a , t1.b , t2.a , t2.b);
    return 0;
}
Running result : 0 20 1 20
正确答案: B C   你的答案: B C (正确)

A static/const
B const/static
C --/static
D conststatic/static
E None of above
*/


/*
explicit关键字强制仅有显式调用有效 ,正确,C++提供关键字explicit,用于阻止不应该允许的经过转换构造函数进行的隐式转换的发生。
声明为explicit的构造函数不能在隐式转换中使用。
普通 构造函数 能够被 隐式调用 。而explicit 构造函数 只能被显式调用
*/

/*
关于static变量,请选择下面所有说法正确的内容。
正确答案: A B C   

A若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度
B若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度
C设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题
D静态全局变量过大,可那会导致堆栈溢出

全局变量和静态变量放在全局区,也称静态区,不放在堆区或栈区,故不会引起堆栈溢出 .D是错误的。
*/ 

/*
设p是指针变量,语句P = NULL;等价于? p=0
*/
/
/*
以下程序是用辗转相除法来计算两个非负数之间的最大公约数:
long long gcd(long long x, long long y) {
    if (y == 0)
        return x;
    else
        return gcd(y, x % y);
}
我们假设x,y中最大的那个数的长度为n,x>y,基本运算时间复杂度为O(1),那么该程序的时间复杂度为( )

正确答案: B  

A O(1)
B O(logy)
C O(n)
D O(x)
*/

/*
下面哪种情况下,B不能隐式转换为A?
正确答案: B   

A class B:public A{}
B class A:public B{}
C class B{operator A();}
D class A{A(const B&);}

A 派生类转换为基类
B 基类转派生类,不能隐式转换
C 是隐式类型转换操作符
D 通过拷贝构造函数进行隐式转化
*/
///
/*
下述有关c++的虚类和java接口的描述,说法错误的是?
正确答案: D   你的答案: D (正确)

A c++虚类相当与java里面的抽象类
B c++中没有接口的概念,与之对应的是纯虚类,对应的是java的接口
C 纯虚函数和虚函数的区别在于前者不包含定义,而后者可以包含函数体。
D 一个抽象类和接口中的方法必须是抽象方法

抽象类 : 类中至少有一个方法是抽象方法,则该类就是抽象类
接口 :类中的方法全部都是抽象方法。
1、一个子类只能继承一个抽象类(虚类),但能实现多个接口;
2、一个抽象类可以有构造方法,接口没有构造方法;
3、一个抽象类中的方法不一定是抽象方法,即其中的方法可以有实现(有方法体),接口中的方法都是抽象方法,不能有方法体,只有声明;
4、一个抽象类可以是public、private、protected、default,
   接口只有public;
5、一个抽象类中的方法可以是public、private、protected、default,
   接口中的方法只能是public和default
*/

/*
不能把字符串"HELLO!"赋给数组b的语句是()
正确答案: B   你的答案: B (正确)

A char b[10]={'H','E','L','L','O','!','\0'};
B char b[10];b="HELLO!";
C char b[10];strcpy(b,"HELLO!");
D char b[10]="HELLO!";
*/
///
/*
int f(unsigned int n)
{ 
   unsigned int m=0;
   for(m=0;n;++m)
   {
     n&=(n-1);
    }
    return m;
}
f(2486)的返回值是()
正确答案: A   你的答案: A (正确)

A 7
B 10
C 15
D 1243
二进制1的个数

/*
下列关于C/C++的宏定义的说法中,不正确的是:
正确答案: A   你的答案: A (正确)

A宏定义的常量更容易理解,如果可以使用宏定义常量的话,要避免使用 const常量
B宏的嵌套定义过多会影响程序的可读性,而且很容易出错
C相对于函数调用,宏定义可以提高程序的运行效率
D宏定义不检查参数正确性,会有安全隐患
*/

/*
关于抽象类和纯虚函数的描述中,错误的是
正确答案: D   

A纯虚函数的声明以“=0;”结束
B有纯虚函数的类叫抽象类,它不能用来定义对象
C抽象类的派生类如果不实现纯虚函数,它也是抽象类
D纯虚函数不能有函数体

纯虚函数是可以有函数体的,且函数体可以定义在类内部或者类外部
*/

/*
#include <iostream>
using namespace std;
 
class A
{
public:
    A()
    {
        printf("A");
    }
};
 
int main()
{
    A *p1 = new A;
    A *p2 = (A *)malloc(sizeof(A));
     
    return 0;
}
该程序运行结果为
正确答案: A   你的答案: A (正确)

A A
B AA
C 崩溃
D 不可预测

new会分配内存,并调用类的构造函数创建对象,而malloc只是分配内存,不调用类的构造函数创建对象,
这个程序应该用delete p1;显示释放掉p1所指的堆上的内存,这样才会调用类的析构函数,否则不会调用。
*/
///
/*
下列选项中,会导致用户进程从用户态切换到内核的操作是?
I. 整数除以零 
II. sin( )函数调用   
III. read系统调用
正确答案: B   你的答案: B (正确)

A 仅 I、II
B 仅 I、III
C 仅 II 、III
D I、II和III

用户态切换到内核态的  3  种方式
a.  系统调用
b.  异常
c.  外围设备的中断 

I. 异常 
III. 系统调用 
*/

/*
具有相同类型的指针类型变量p与数组a,不能进行的操作是:
正确答案: D   你的答案: D (正确)

p=a;
*p=a[0];
p=&a[0];
p=&a;
数组名可以转化成指向该数组首元素的内存地址,即本题中a可代表数组a的第一个元素的内存地址, 因此p = a;合法;
同样地,p = &a[0]也合法( &a[0]表示数组a的 第一个元素内存地址 )。
*操作符是解引用操作,*p则表示p所指向的对象的值。*p = a[0];表示将a[0]赋值给p所指的对象,是合法的。
对于选项D,&a表示数组a的地址
*/
/
/*
面向对象的三个基本元素是什么?
正确答案: A B D   你的答案: A B D (正确)

A封装
B继承
C重载
D多态
1. 封装: 封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。
面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。 
2. 继承: 继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。
对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。  
3. 多态: 多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。
多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。
C++ 中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,
然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。
所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。
比如:模板技术, RTTI 技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。

五个基本原则: 
1单一职责原则(Single-Resposibility Principle):一个类,最好只做一件事,只有一个引起它的变化。
2单一职责原则可以看做是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。 
开放封闭原则(Open-Closed principle):软件实体应该是可扩展的,而不可修改的。也就是,对扩展开放,对修改封闭的。
3Liskov替换原则(Liskov-Substituion Principle):子类必须能够替换其基类。
这一思想体现为对继承机制的约束规范,只有子类能够替换基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基础。 
4依赖倒置原则(Dependecy-Inversion Principle):依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;
抽象不依赖于具体,具体依赖于抽象。 
5接口隔离原则(Interface-Segregation Principle):使用多个小的专门的接口,而不要使用一个大的总接口。
*/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值