1.对于内置类型而言,new仅仅是分配内存,除非后面显示加(),相当于调用它的构造函数,对于自定义类型而言,只要一调用new,那么编译器不仅仅给它分配内存,还调用它的默认构造函数初始化,即使后面没有加()
2.
1
2
3
4
5
6
7
|
enum
string{
x1,
x2,
x3=
10
,
x4,
x5,
} x;
|
函数外部问x等于什么?
- 5
- 12
- 0
- 随机值
enum只是定义了一个常量集合,里面没有“元素”,枚举类型是当做int类型存储的, sizeof值都为4 ,并且系统为其初始化为0;
但是在vs2015中,sizeof 值的确是4,但输出x报错:
使用了未初始化的局部变量“x”
3.
1
2
3
4
5
6
7
8
9
10
11
12
|
void
example(
char
acWelcome[]) {
printf
(
"%d\n"
,
sizeof
(acWelcome));
return
;
}
void
main() {
char
acWelcome[] =
"Welcome to Huawei Test"
;
example(acWelcome);
cout <<
sizeof
(acWelcome) <<
" "
<<
strlen
(acWelcome) << endl;
system
(
"pause"
);
return
;
}
|
输出结果:4
23 22
32位系统是4 64位系统是8,数组作为函数的参数是会退化为函数指针的,想想看,数组作为函数参数的时候经常是需要传递数组大小的
4.
虚函数也是类的成员函数,A说法是不正确的;
虚函数和函数重载都实现了C+=的多态性,但表现形式不一样,函数重载调用根据参数个数、参数类型等进行区分,而虚函数则是根据动态联编来确定调用什么。
函数重载可以是类的成员函数也可以是非成员函数,比如:
1
2
|
int
fun(
int
a);
int
fun(
int
a,
int
b);
|
这就是非成员重载,虚函数必须是成员函数了,否则就失效了。
5.
处理a.html文件时,以下哪行伪代码可能导致内存越界或者抛出异常()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
int
totalBlank =
0
;
int
blankNum =
0
;
int
taglen = page.taglst.size();
A
for
(
int
i =
1
; i < taglen-
1
; ++i)
{
//check blank
B
while
(page.taglst[i] ==
"<br>"
&& i < taglen)
{
C ++totalBlank;
D ++i;
}
E
if
(totalBlank >
10
)
F blankNum += totalBlank;
G totalBlank =
0
;
}
|
答案为B,因为while(page.taglst[i] == "<br>" && i < taglen)这个判断,先执行page.taglst[i] == "<br>"这个判断,如果这个判断返回值为true,再执行i < taglen这个判断。当i=taglen的时候,执行page.taglst[i] == "<br>"这个判断就会越界,所以B处,最先出现越界。
6.
设已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为?
1
2
3
4
5
6
7
8
|
C c;
void
main()
{
A*pa=
new
A();
B b;
static
D d;
delete pa;
}
|
构造函数调用顺序:CDAB
析构函数调用顺序:ABDC
这道题主要考察的知识点是 :全局变量,静态局部变量,局部变量空间的堆分配和栈分配
其中全局变量和静态局部变量时从 静态存储区中划分的空间,
二者的区别在于作用域的不同,全局变量作用域大于静态局部变量(只用于声明它的函数中),
而之所以是先释放 D 在释放 C的原因是, 程序中首先调用的是 C的构造函数,然后调用的是 D 的构造函数,析构函数的调用与构造函数的调用顺序刚好相反。
局部变量A 是通过 new 从系统的堆空间中分配的,程序运行结束之后,系统是不会自动回收分配给它的空间的,需要程序员手动调用 delete 来释放。
局部变量 B 对象的空间来自于系统的栈空间,在该方法执行结束就会由系统自动通过调用析构方法将其空间释放。
之所以是 先 A 后 B 是因为,B 是在函数执行到 结尾 "}" 的时候才调用析构函数, 而语句 delete a ; 位于函数结尾 "}" 之前。
7.
若char是一字节,int是4字节,指针类型是4字节,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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)的值是多少?
(1) 12=1(char)+3(对齐)+4(int)+4(虚函数表)
(2) 9=1(char)+3(对齐)+4(int)
在类中,如果什么都没有,则类占用1个字节,一旦类中有其他的占用空间成员,则这1个字节就不在计算之内,如一个类只有一个int则占用4字节而不是5字节。
如果只有成员函数,则还是只占用1个字节,因为类函数不占用空间
虚函数因为存在一个虚函数表,需要4个字节,数据成员对象如果为指针则为4字节,注意有字节对齐,如果为13字节,则进位到16字节空间。
8.
方法重载(overload):
1.必须是同一个类
2方法名(也可以叫函数)一样
3参数类型不一样或参数数量不一样
方法的重写(override)两同两小一大原则:
方法名相同,参数类型相同
子类返回类型小于等于父类方法返回类型,
子类抛出异常小于等于父类方法抛出异常,
子类访问权限大于等于父类方法访问权限。
9.输出数组的全排列:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
void
perm(
int
list[],
int
k,
int
m)
{
if
(k == m)
{
copy(list, list + m, ostream_iterator<
int
>(cout,
" "
));
cout << endl;
return
;
}
for
(
int
i = k; i<m; i++)
{
swap(list[k], list[i]);
perm(list, k + 1, m);
swap(list[k], list[i]);
}
}
void
main(
void
)
{
int
arr[] = { 1,2,3 };
perm(arr, 0, 3);
system
(
"pause"
);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
//参数为引用,函数调用多,所以定义为内联函数
inline
void
charSwap(
char
&_left,
char
&_right)
{
// 交换_left和_right
char
temp = _left;
_left = _right;
_right = temp;
}
//arr为字符数组,nPrefix表示前缀的下标,nSize表示arr大小(字符个数)
void
fullPermulation(
char
arr[],
int
nPrefix,
int
nSize)
{
//打印arr[]的全排列
int
i = 0;
if
(nPrefix == nSize - 1)
{
//前缀是最后的位置,打印一个排列
for
(i = 0; i<nSize; i++)
putchar
(arr[i]);
putchar
(
'\n'
);
}
else
{
//arr[nPrefix...nSize-1]有多种排列方式,递归地产生这些排列方式
for
(i = nPrefix; i<nSize; i++)
{
if
(i != nPrefix)
charSwap(arr[nPrefix], arr[i]);
//交换前缀,产生下一次前缀
fullPermulation(arr, nPrefix + 1, nSize);
if
(i != nPrefix)
charSwap(arr[nPrefix], arr[i]);
//恢复原有的顺序
}
}
}
int
main()
{
char
arr[] = {
'1'
,
'2'
,
'3'
};
fullPermulation(arr, 0,
sizeof
(arr) /
sizeof
(
char
));
system
(
"pause"
);
return
0;
}
|
10.static 修饰局部变量:1)只有第一次进入函数时初始化
2)生命期在离开main函数时结束
3)存储在全局区
4)不重新初始化
11.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
#include<iostream>
using namespace std;
class
MyClass
{
public
:
MyClass(
int
i =
0
)
{
cout << i;
}
MyClass(
const
MyClass &x)
{
cout <<
2
;
}
MyClass &operator=(
const
MyClass &x)
{
cout <<
3
;
return
*
this
;
}
~MyClass()
{
cout <<
4
;
}
};
int
main()
{
MyClass obj1(
1
), obj2(
2
);
MyClass obj3 = obj1;
return
0
;
}
|
122444
C MyClass obj3 = obj1;
obj3还不存在,所以调用拷贝构造函数输出
2
,
如果obj3存在,obj3=obj,则调用复制运算符重载函数,输出
3
12.
如下代码输出结果是什么?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include<stdio.h>
char
*myString()
{
char
buffer[
6
] = {
0
};
char
*s =
"Hello World!"
;
for
(
int
i =
0
; i < sizeof(buffer) -
1
; i++)
{
buffer[i] = *(s + i);
}
return
buffer;
}
int
main(
int
argc,
char
**argv)
{
printf(
"%s\n"
, myString());
return
0
;
}
|
字符数组是在栈区分配的,函数返回后就被回收了,所以指针指向的值未知。这是将字符数组赋值写在非main函数中设置的陷阱。
当函数返回值之后,其函数内部的栈空间均会被销毁;
在函数内部,若程序员没有为指针分配空间,则函数退出时,其栈空间也就不存在了;
因此,使用数组时,不能返回一个数组;
但是 上述代码在VS2015环境中输出为Hello.