选择题
解析:函数的形参是引用类型,我们直接传变量本身就可以。
形参的改变也会引起实参的改变,叫做输出型参数。
解析:本题考查内存申请和释放问题。在C++中,内存申请和释放尽量要匹配使用:
malloc/calloc/realloc
和free
匹配使用;new
和delete
匹配使用;new[]
和delete[]
匹配使用。使用
new
申请空间和delete
销毁空间时过程:1.
new T
:调用operator new()
申请空间,其实operator new()
函数内部还是使用malloc
申请空间,然后调用T
的构造函数对申请的空间进行初始化;
delete p
:先调用析构函数释放p指向对象中的资源,再调用operator delete()
释放p
所指向的空间,实质上函数内部是使用free
释放空间的。2.
new T[]
:调用operator new[]()
申请空间,其实内部是使用operator new()
申请空间,然后调用N
次T
的构造函数对申请的空间进行初始化;
delete[] p
:先调用N次析构函数释放p指向的N个对象中的资源,再调用operator delete[]()
释放p
所指向的空间,实质上函数内部是调用operator delete()
释放空间的。
new [5]
申请5个ClassA
类型的空间,同时会调用构造函数5次,对于new []
申请的空间,要用delete []
进行释放,如果用delete
进行释放,很有可能会报错,所以题目中delete
只会释放一个空间,调用一次析构函数。
解析:
malloc
是在堆上申请空间,而new
内部也使用malloc
申请空间,所以new
动态申请的内存在堆区。
解析:静态成员特性:
1.静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区 ;
2.静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
3.在类外访问静态成员变量(成员变量访问限定符为
public
)时:对象.静态成员变量 || 类名::静态成员变量4.静态成员函数没有隐藏的
this
指针,不能访问任何非静态成员5.静态成员也是类的成员,受public、protected、private 访问限定符的限制
要使用静态的数据成员的时候,在静态成员名前面加上类名和作用域符号(
::
),静态成员属于类的所有对象,要在类域外面进行定义初始化,当然静态变量要加上static
。在类外这样定义和访问:
解析:
class
定义的类的默认访问权限是私有private
,struct定义的类的默认访问权限是public
。
解析:类的非静态成员函数形参中有隐藏的
this
指针,参数表中没有任何参数说明是一个一元运算符的重载;前置运算符重载为成员函数时,参数列表中不给参数,但是后置运算符一般会给一个参数以示区别,比如前置++
,用operator+()
;后置++,用operator+(int)
区分。
解析:obj(1)和obj(2)是直接调用构造函数,obj3(obj1)调用拷贝构造,所以这里会打印112,然后就是return 0,调用析构函数,先构造的后析构,然后会打印444。
解析:静态成员不能在类内初始化,要在类外初始化;
静态成员为类对象所共有的,可以被类对象调用;
既然是成员就可以被访问限定符的限定;
公共成员可以直接用类名进行调用。
解析:如果把构造函数设成私有,那么在类外
new
一个空间的时候就会报错;如果把析构函数设成私有,那么可以用new
类创建,但是不能直接用delete
释放空间,可以通过在类里面创建一个函数专门用来调用delete
,能够释放空间。
解析:函数模板格式:
template<typename T1, typename T2,......,typename Tn>
,注意:typename
是用来定义模板参数关键字,也可以使用class
,不能使用struct
代替class
。
编程题
1.另类加法
答案解析:本题的意思是自己实现加法,不适用现成的运算符,考察大家对于运算符的灵活运用
解题思路:
本题可以通过位运算实现,具体实现如下:
两个数求和,其实就是 求和后当前位的数据+两个数求和的进位例如:
1 + 2; 00000001 + 00000010
求和后当前位的数据: 00000011 ; 求和后的进位数据: 没有进位,则 00000000
两者相加,则得到: 00000011 就是3
2 + 2; 00000010 + 00000010
求和后当前位的数据: 00000000, 1和1进位后当前为变成0了
求和后进位的数据: 00000100, 两个1求和后进位了
相加后得到: 00000100 就是4求和后当前位的数据:简便的计算方法就是两个数进行异或 00000001 ^ 00000010 -> 00000011
求和后进位的数据:简便的计算方法就是两个数相与后左移一位 (00000010 & 00000010) << 1
所以这道题使用递归更加容易理解
个人理解:当使用^计算时,得到的是两个数中相同权重位不同数值的结果;使用&计算得到的是相同位中都为1计算得到的结果,计算的也就是需要向前进位的那一位,所以计算得到的结果左移一位;本来应该是这两个计算结果相加得到最终结果,但是不允许使用+号,所以再次将两个结果进行递归计算。
class UnusualAdd {
public:
int addAB(int A, int B) {
// write code here
if(A == 0)
return B;
if(B == 0)
return A;
int sum = A ^ B;//不考虑进位时候相加的结构
int ret = (A&B) << 1;//计算进位的数据
return addAB(sum, ret);
}
};
/*
异或是不进位的加法
0001 ^
0011
0010
相与后左移一位即可得到进位的数据
0001 &
0011
0001 << 1
0010
0010 ^
0010
0000
0010 &
0010
0010 <<
0100 最终结果
*/
class UnusualAdd {
public:
int addAB(int A, int B) {
if(A == 0) // 任意一个为0的时候就截止
return B;
if(B == 0)
return A;
int noCarry = A^B;
int carry = (A&B)<<1;
return addAB(noCarry, carry);
}
};
/*
最终结果其实就是 A^B + (A&B)<<1
但是不能使用+,因此循环处理右边的部分,直到为0才出来
*/
class UnusualAdd {
public:
int addAB(int A, int B) {
while(B != 0){
int a = A^B;
int b = (A&B)<<1;
A = a;
B = b;
}
return A;
}
};
2.走方格的方案数
解析:本题为求取路径总数的题目,一般可以通过递归求解,对于复杂的问题,可以通过动态规划求解。此题比较
简单,可以通过递归解答。
【解题思路】:| 1 | 2 | 3 |
| 4 | 5 | 6 |
| 7 | 8 | 9 |
- 对于上面的nm(33)的格子,有两种情况
a. 如果n或者m为1,则只有一行或者一列,从左上角走到右下角的路径数为n + m
比如: 1 * 1格子,可以先向下走,再向右走,到达右下角;或者先向右走,
再向下走,到达右下角,共两条,即 1 + 1 = 2,对于1 * m和 n * m的
情况同学们自己画一下
b. 如果n,m都大于1,那么走到[n][m]格子的右下角只有两条路径,
<1>: 从[n - 1][m]格子的右下角向下走,到达
<2>: 从[n][m - 1]格子的右下角向右走,到达
所以走到[n][m]格子的右下角的数量为[n-1][m] + [n][m - 1],可以通过递归实现,情况a为递归的终止条件。
#include<iostream>
using namespace std;
int pathNum(int n,int m)
{
if(n > 1 && m > 1)
//b情况,递归
return pathNum(n-1,m) + pathNum(n,m-1);
else if(((n >= 1)&&(m == 1))||((n == 1)&&(m >= 1)))
// a情况,终止条件
return n + m;
else
//格子为0时, 路径为0
return 0;
}
int main()
{
int n,m;
while(cin>>n>>m)
{
cout<<pathNum(n,m)<<endl;
}
return 0;
}