笔试题

目录

1.给出下列程序运行后的输出结果

2.下面哪个保留字不能作为函数的返回类型?

3.假定a为一个整数型数组名,则元素a[4]的字节地址为

4.假定AB为一个类,则执行“AB a(4),b[3],*p[2]”语句时,自动调用该类构造函数的次数为

5.以下反向遍历array数组的方法有什么错误?(负数时的无符号整型)

6.以下两条输出语句分别输出什么?(( int a)和(int&)a的区别)

7.以下代码有什么问题?(true?1:"1")

8.以下代码有什么问题?(vector earse时迭代器失效问题)

9.用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)

10.写一个标准宏MIN,这个宏输入两个参数并返回较小的一个。

11.  用变量a给出下面的定义

12.下面代码输出是什么?(交换,函数和宏函数)

13.下面代码输出是什么?(构造析构顺序)

14.请说明下面定义中的三个const分别起什么作用(const)

15.完成Mycomp,使得数组a按字符串长度排序,字符串长度一样时,按字符串大小排序。(stl sort的用法)

16.字符串替换

 

1.给出下列程序运行后的输出结果

1)

#include<iostream.h>
#include<string.h>
void main()
{
    char *a[5] = {"student", "worker", "cadre", "soldier", "peasant"};
    char *p1,*p2;
    p1 = p2 = a[0];
    for(int i = 0; i < 5; i++)
    {
        if(strcmp(a[i],p1)>0) p1 = a[i];
        if(strcmp(a[i],p2)<0) p2 = a[i];

    }
    cout<<p1<<" "<<p2<<endl;
}

worker cadre

2)

#include<iostream.h>
int a = 5;
void main()
{
    int a=10,b=20;
    cout<<a<<" "<<b<<endl;
    {
        int a=0,b=0;
        for(int i=1;i<6;i++)
        {
            a+=i;
            b+=a;
        }
        cout<<a<<" "<<b<<" "<<::a<<endl;
    }
    cout<<a<<" "<<b<<endl;
    
}

解析:

1+2+3+4+5=15

1+3+6+10+15=35

全局作用域符号:当全局变量在局部函数中与其中某个变量重名,那么就可以用::来区分.

 

2.下面哪个保留字不能作为函数的返回类型?

A.void        B.int       C.new       D.Long

答案:C

 

3.假定a为一个整数型数组名,则元素a[4]的字节地址为

A.a+4      B.a+8        C.a+16      D.a+4*sizeof(int)

 

4.假定AB为一个类,则执行“AB a(4),b[3],*p[2]”语句时,自动调用该类构造函数的次数为

A.3          B.4        C.6         D.9

答案:B

(1)a(2):意思是定义了一个变量叫a,并使用还有一个参数的构造函数完成构造;

(2)b[3]:定义了一个数组,数组中有3个元素,每一个元素都是AB的实例,为确保实例在使用前已经构造,编译器会自动调用没有参数的构造器3次,一次这里就调用了3次无参数构造器;

(3)*p:这里仅仅定义了一个指针,因此编译器不掉用构造器

AB a(4),b(5),c[3],*p[2]={&a,&b}; 5次

只有给对象分配内存才会调用构造函数。指针没有new一个对象,所以不会分配内存,不构造。 只是给指针指向某地值的话,没有开辟空间,不构造。只是指针指向两个对象,没有构造新的对象

 

5.以下反向遍历array数组的方法有什么错误?(负数时的无符号整型)

    vector array;
    array.push_back(1);
    array.push_back(2);
    array.push_back(3);
    //方向遍历array数组
    for(vector::size_type i = array.size()-1; i>0; --i)
    {
        cout<<array[i]<<endl;
    }

1)vector<int> array;

2)vector<int>size_type

3)首先for循环应该是i>=0,但是:

vector::size_type被定义为unsigned int,即无符号数,这样做为循环变量的i为0时再减1就会变成最大的整数,导致循环失去控制。关于-1时的无符号整型会变成最大整数请参考:https://blog.csdn.net/ljianhui/article/details/10367703

https://blog.csdn.net/beibaoke910/article/details/88781591

可改为for(int i = array.size()-1; i>=0; --i)

参考:https://blog.csdn.net/zhuimengzh/article/details/6686542  反向遍历array

 

6.以下两条输出语句分别输出什么?(( int a)和(int&)a的区别)

    float a = 1.0f;
    cout<<(int)a<<endl;
    cout<<(int&)a<<endl;
    cout<<boolalpha<<((int)a==(int&)a)<<endl;
    
    float b = 0.0f;
    cout<<(int)b<<endl;
    cout<<(int&)b<<endl;
    cout<<boolalpha<<((int)b==(int&)b)<<endl;

答案:

解析:

(int)a a在内存中的值转换成int类型 ,取a的整数部分 。

(int&)a 不经过转换, 直接得到a在内存单元的值,并将其转换成整数输出。(其实(int&)a就是将a转换为int型的引用。如 int&b=(int&)a)

boolalpha是头文件#include <iostream>中的一个函数,是把bool a = 1;变量打印出false或者true的函数。

参考:https://blog.csdn.net/Lina_ACM/article/details/73717718 ( int a)和(int&)a的区别

            https://blog.csdn.net/u011478505/article/details/46507761 (int)a、&a、(int)&a、(int&)a的区别

 

7.以下代码有什么问题?(true?1:"1")

cout<<true?1:"1"<<endl;

答:三元表达式“?:”问号后面的两个操作数必须为同一类型.隐式转换也可以,如:true?1:'1'。

 

8.以下代码有什么问题?(vector earse时迭代器失效问题)

    typedef vector IntArray;
    IntArray array;
    array.push_back(1);
    array.push_back(2);
    array.push_back(2);
    array.push_back(3);
    //删除数组中所有的2
    for(IntArray::iterator itor = array.begin(); itor != array.end(); ++itor)
    {
        if(2==*itor)
        {
            array.erase(itor);
        }
    }

1)typedef vector<int> IntArray;

2)迭代器失效问题,应修改为

     for(IntArray::iterator itor = array.begin(); itor != array.end();)
    {
        if(2==*itor)
        {
            itor = array.erase(itor);
        }
        else
        {
            ++itor;
        }

    }

解析:

 对于序列式容器,比如vector,删除当前的iterator会使后面所有元素的iterator都失效。这是因为顺序容器内存是连续分配(分配一个数组作为内存),删除一个元素导致后面所有的元素会向前移动一个位置。(删除了一个元素,该元素后面的所有元素都要挪位置,所以,iter++,已经指向的是未知内存)。

但是erase方法可以返回下一个有效的iterator,所以改为满足条件时itor = array.erase(itor),这样删除itor指向的元素后,返回的是下一个元素的迭代器,这个迭代器是vector内存调整过后新的有效的迭代器;不满足条件时++itor.

map的earse方法:

for( itMap = Map.begin(); itMap != Map.end(); )
{       
    if( WillDelete(*itMap) )
    {
        map<int, int>::iterator tmpIter = itMap;
        itMap++;
        Map.erase(tmpIter)
    }
    else
    {
        itMap ++;
    }
 }
//或者
for( itMap = Map.begin(); itMap != Map.end(); )
{       
    if( WillDelete(*itMap) )
    {
        Map.erase(itMap ++)
    }
    else
    {
        itMap ++;
    }
 }

参考: https://www.cnblogs.com/zsq1993/p/5930229.html  vector中earse用法注意事项

            https://blog.csdn.net/lujiandong1/article/details/49872763 迭代器失效的几种情况总结

 

9.用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)

#define SECONDS_PER_YEAR (60*60*24*365)UL

解析:

  1). #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)

  2). 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。

  3). 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。

  4). 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。

 

10.写一个标准宏MIN,这个宏输入两个参数并返回较小的一个。

#define Min(a,b) ( ((a)>=(b))?(b):(a))  一定要注意加括号

   

11.  用变量a给出下面的定义

(a) 一个整型数(An integer)

(b) 一个指向整型数的指针(A pointer to an integer)

(c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)

(d) 一个有10个整型数的数组(An array of 10 integers)

(e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)

(f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)

(g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)

(h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer )

 

https://blog.csdn.net/wqx521/article/details/76623064

答案:

(a) int a; // An integer

(b) int *a; // A pointer to an integer

(c) int **a; // A pointer to a pointer to an integer

(d) int a[10]; // An array of 10 integers

(e) int *a[10]; // An array of 10 pointers to integers

(f) int (*a)[10]; // A pointer to an array of 10 integers

(g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer

(h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer

定义一个指针指向XXX,先把XXX定义出来,再把(*a)替换XXX对变量名

https://www.cnblogs.com/mq0036/p/3382732.html 数组指针和指针数组的区别

 

12.下面代码输出是什么?(交换,函数和宏函数)

#include “stdio.h”
#define swap1(a,b) a=a+b;b=a-b;a=a-b;
int swap2(int a, int b)
{
    int temp = a;
    b=a;
    a=temp;
    return 0;
}
void main()
{
    int x=5, y=10;
    swap1(x,y);
    printf("%d %d\n", x, y);
    swap2(x,y);
    printf("%d %d\n", x, y); 
}

结果:

解析:第二行为宏定义,形参为a和b,第12行宏调用中实参为x和y,在宏展开时用x代替a,用y代替b,再用a=a+b;b=a-b;a=a-b;代替swap1得到如下语句:x=x+y;y=x-y;x=x-y; ,所以打印结果为 10 5。而swap2函数没交换实参的值,所以依然是10 5。

参考:https://blog.csdn.net/swpu_yx32/article/details/52858684 c语言带参宏定义

 

13.下面代码输出是什么?(构造析构顺序)

#include<iostream>
using namespace std;
 
class C
{
    int a;
public:
    C(int aa=0) { a=aa; }
    ~C() { cout<<"Destructor C!"<<a<<endl;}
};
 
class D: public C
{
    int b;
public:
    D(int aa=0, int bb=0):C(aa) { b=bb; }
    ~D() { cout<<"Destructor D!"<<b<<endl;}
};
 
void test()
{
    D x(5);
    D y(6,7);
}
 
void main()
{
    test();
}

Destructor D!7

Destructor C!6

Destructor D!0

Destructor C!5

总结:构造析构顺序

不存在继承关系:对象成员(声明顺序),类本身

存在继承关系:基类,派生类对象成员,派生类

析构顺序则和构造顺序完全相反。

 

参考:https://blog.csdn.net/beibaoke910/article/details/88669401

class MyA
{
public:
    MyA()
    {
        Fun(__FUNCTION__);
    }
    ~MyA()
    {
        Fun(__FUNCTION__);
    }
    virtual void Fun(const char* funName)
    {
        printf("%s: I am A\n", funName);
    }
};
class MyB: public MyA
{
public:
    MyB()
    {
        Fun(__FUNCTION__);
    }
    ~MyB()
    {
        Fun(__FUNCTION__);
    }
    virtual void Fun(const char* funName)
    {
        printf("%s: I am B\n", funName);
    }
};
int  main()
{
    MyA * a = new MyA;
    MyB * b = new MyB;
    delete b;
    delete a;
}

MyA: I am A
MyA: I am A
MyB: I am B
~MyB: I am B
~MyA: I am A
~MyA: I am A

若main函数改为

int  main()
{
    MyA * a = new MyA;
    MyA * b = new MyB;
    delete b;
    delete a;
}

输出结果变为:

MyA: I am A
MyA: I am A
MyB: I am B
~MyA: I am A
~MyA: I am A

因为析构函数不是虚析构。

14.请说明下面定义中的三个const分别起什么作用(const)

class B
{
public:
    void f(const int * const a) const;
};

左物右指。第一个const是说不能通过*a解引用的方法改变a所指向的数据,第二个const是指指针a不能指向其他内存地址,第三个const是说该函数是const成员函数,不能修改成员变量,不能调用非const成员函数。

参考:https://blog.csdn.net/beibaoke910/article/details/79841276

15.完成Mycomp,使得数组a按字符串长度排序,字符串长度一样时,按字符串大小排序。(stl sort的用法)

int main()
{
    std::vector<std::string> strs;
    std::sort(strs.begin(), strs.end(), MyComp() );
    struct MyComp
    {

    };
}

答案: 

 

    struct MyComp
    {
        bool operator()(const std::string &str1, const std::string &str2)
        {
            int len1 = str1.length();
            int len2 = str2.length();
            if(len1!=len2)
            {
                return (len1<len2);
            }
            return (str1.compare(str2)<0);
        }
    };

测试:

int main()
{
    std::vector<std::string> strs;
    strs.push_back("hi");
    strs.push_back("hello");
    strs.push_back("world");
    strs.push_back("123");
    strs.push_back("bcde");
    strs.push_back("bbcd");
    std::sort(strs.begin(), strs.end(), MyComp() );
    for (int i = 0; i < 6; i++)
    {
        cout<<strs[i]<<endl;
    }
}

参考:https://blog.csdn.net/beibaoke910/article/details/89286806

16.字符串替换

      replacedas$REPLACE_ME$fj32RE3$REPLACE_ME$ad34$REPLACE_ME$2R34$REPLACE_ME$,将字符串中的$REPLACE_ME$替换成HELLO

std::string Replace(const std::string& strSrc, const std::string& strRaw, const std::string& strReplace)
{
	if (strSrc.empty())
	{
		return strSrc;
	}
	std::string strRet;
	std::string strToBeAnalysis = strSrc;
	do 
	{
		int nPos = strToBeAnalysis.find(strRaw);
		if (nPos == std::string::npos)
		{
			strRet += strToBeAnalysis;
			break;
		}
		strRet += strToBeAnalysis.substr(0, nPos);
		strRet += strReplace;

		strToBeAnalysis = strToBeAnalysis.substr(nPos + strRaw.length());
	} while (true);
	return strRet;
}


int main()
{
	string str = "replacedas$REPLACE_ME$fj32RE3$REPLACE_ME$ad34$REPLACE_ME$2R34$REPLACE_ME$";
	string strRest = Replace(str, "$REPLACE_ME$", "HELLO");
	cout << strRest << endl;
	return 0;
}

 

16.实现一个类智能指针包含构造函数,拷贝构造函数,析构函数,赋值运算符,->运算符

14.实现一个简单的类,使其只能在栈上分配对象。

写一个不可继承的类

15.实现一个简单的类(Singleton)

7.右值函数作用

8.不借助宏,定义一种类型,在32位程序中为32位整数,在64位程序中为64位整数(windows/linux兼容)

10.使C++代码更健壮的方法(越多越好)

简述指针和引用的区别

 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值