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
|
class
Base {
public
:
Base(
int
j): i(j) {}
virtual
~Base() {}
void
func1() {
i *= 10;
func2();
}
int
getValue() {
return
i;
}
protected
:
virtual
void
func2() {
i++;
}
protected
:
int
i;
};
class
Child:
public
Base {
public
:
Child(
int
j): Base(j) {}
void
func1() {
i *= 100;
func2();
}
protected
:
void
func2() {
i += 2;
}
};
int
main() {
Base * pb =
new
Child(1);
pb->func1();
cout << pb->getValue() << endl;
delete
pb; }
|
11
101
12
102
1
2
3
4
|
const
char
str1[]=”abc”;
const
char
str2[]=”abc”;
const
char
*p1 = “abc”;
const
char
*p2 = “abc”;
|
str1和str2地址不同,P1和P2地址相同。
str1和str2地址相同,P1和P2地址相同。
str1和str2地址不同,P1和P2地址不同。
str1和str2地址相同,P1和P2地址不同。
1
2
3
4
5
6
7
8
9
|
#include<stdio.h>
#include<stdlib.h>
void
main()
{
int
a = -3;
unsigned
int
b = 2;
long
c = a + b;
printf
(
"%ld\n"
,c);
}
|
-1
4294967295
0x7FFFFFFF
0xFFFFFFFF
| Which of the following statements are true? |
We can create a binary tree from given inorder and preorder traversal sequences.
We can create a binary tree from given preorder and postorder traversal sequences.
For an almost sorted array, insertion sort can be more effective than Quicksort.
Suppose T(n) is the runtime of resolving a problem with n elements, T(n) = Θ(1) if n = 1; T(n) = 2T(n/2) + Θ(n) if > 1; so T(n) is Θ(n log n).
None of the above.
1
2
3
4
5
6
|
#define F(X,Y) (X)--, (Y)++, (X)*(Y);
…
int
i, a = 3, b = 4;
for
( i = 0; i<5; i++)
F(a,b) ;
printf
(“%d, %d”, a, b);
|
|
3, 4
3, 5
-2, 5
-2, 9
gstrin
string
srting
stirng
| () 的作用是将源程序文件进行处理,生成一个中间文件,编译系统将对此中间文件进行编译并生成目标代码。 |
编译预处理
汇编
生成安装文件
编译
1
2
3
4
5
6
|
char
* s1 =
"Hello world"
;
char
s2[] =
"Hello world"
;
s1[2] =
'E'
;
// 1
s2[2] =
'E'
;
// 2
*(s1 + 2) =
'E'
;
// 3
*(s2 + 2) =
'E'
;
// 4
|
语句2、4是非法的
语句3、4是非法的
语句1、3是非法的
仅语句1是非法的
仅语句2是非法的
语句1~4都是合法的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
template
<
typename
T>
void
removeDuplicates(list<T> &aList)
{
T curValue;
list<T>::iterator cur, p;
cur = aList.begin();
while
(cur != aList.end())
{
curValue = *cur;
//空白行
while
(p != aList.end())
{
if
(*p == curValue)
{
//空白行
}
else
{
p++;
}
}
}
}
|
p=curr+1;aList.erase(p++);
p=++curr;aList.erase(p++);
p=curr+1;aList.erase(p);
p=++curr;aList.erase(p);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class
A{
int
i;
};
class
B{
A *p;
public
:
B(){p=
new
A;}
~B(){
delete
p;}
};
void
sayHello(B b){
}
int
main(){
B b;
sayHello(b);
}
|
程序正常运行
程序编译错误
程序崩溃
程序死循环
插入排序
堆排序
冒泡排序
归并排序
选择排序
引用必须被初始化,指针不必。
指针初始化以后不能被改变,引用可以改变所指的对象。
删除空指针是无害的,不能删除引用。
不存在指向空值的引用,但是存在指向空值的指针。
1
2
3
4
5
6
7
8
9
|
struct
A{
void
foo(){
printf
(
"foo"
);}
virtual
void
bar(){
printf
(
"bar"
);}
A(){bar();}
};
struct
B:A{
void
foo(){
printf
(
"b_foo"
);}
void
bar(){
printf
(
"b_bar"
);}
};
|
1
2
3
|
A *p=
new
B;
p->foo();
p->bar();
|
barfoob_bar
foobarb_bar
barfoob_foo
foobarb_fpp
句子
句型
单词
生产式
1:成员对象的构造函数
2:基类的构造函数
3:派生类本身的构造函数
123
231
321
213
, (逗号)
()
. (点)
[]
->
I.A^(BvC)=(A^B)v(A^C)II.Av(B^C)=(AvB)^(AvC)III.(B^A)vC=Cv(A^B)
只有I
只有II
只有I和II
I,II,III;
char *p=”hello”;p[1]=’E’;
char *p=”hello”;char ch=*p++;
int i=0;printf(“%d%d\n”,i++,i--);
都是未定义行为
都不是未定义行为
struct的成员默认是public,class的成员默认是private
struct不能继承,class可以继承
struct可以有无参构造函数
struct的成员变量只能是public
1
2
3
|
char
*p1= “123”, *p2 = “ABC”, str[50]=
"xyz"
;
strcpy
(str+2,
strcat
(p1,p2));
cout << str;
|
xyz123ABC
z123ABC
xy123ABC
出错
1
2
3
4
5
6
|
main()
{
int
a[5]={1,2,3,4,5};
int
*p=(
int
*)(&a+1);
printf
(
"%d"
,*(p-1));
}
|
1
2
5
出现错误
预处理
编译
链接
执行
+和=
=和<<
==和<<
=和[]
- str1和str2毫无干系,他们都是字符常量数组,恰巧存储的值相同而已。"abc"和str1 str2都存储在常量区。str1 str2的地址就是str1[0] str2[0]的地址,即数组首元素所在的地址。
- 后面的两个“abc”存储在常量区,因为他们是字面值(常量),但是p1 p2存储在栈中。其中p1和p2的值不同,但是他们指向同一块静态存储区域。也就是"abc"的地址。
![](http://c.hiphotos.baidu.com/baike/s%3D179/sign=a55b66c4242dd42a5b0905ac3a3a5b2f/adaf2edda3cc7cd9ff6107743801213fb90e91ca.jpg)
![](http://a.hiphotos.baidu.com/baike/s%3D121/sign=4dd6001c0cf41bd5de53ecf660db81a0/1f178a82b9014a90c6cba18aab773912b31bee14.jpg)
![](http://a.hiphotos.baidu.com/baike/s%3D127/sign=9713cc108882b90139adc731448ca97e/a8ec8a13632762d0afec4388a2ec08fa513dc%E6%95%8F%E6%84%9F%E8%AF%8D.jpg)
![](http://e.hiphotos.baidu.com/baike/s%3D157/sign=7620b0def0d3572c62e298d9bd126352/500fd9f9d72a605959dc062d2a34349b033bba3d.jpg)
这题目有问题!详见 http://m.blog.csdn.net/article/details?id=16820035
指针指向字符串时,字符串是常量,存储在常量区,而指针存储在栈区,不能对其操作修改。
1
2
3
4
5
6
7
8
9
10
|
//vector<int> m_vector;
for
(vector<
int
>::iterator iter = m_vector.begin(); iter != m_vector.end();)
{
if
(需要删除)
{
iter=m_vector.erase(iter);
}
else
++iter;
}
|
1
2
3
4
5
6
7
8
9
10
|
//map<int,int> m_map;
for
(map<
int
,
int
>::iterator iter = m_map.begin(); iter != m_map.end(); )
{
if
(需要删除)
{
m_map.erase(iter++);
}
else
++iter;
}
|
|
|
所以,避免未定义行为,是个明智的决定。本文将介绍几种未定义行为,同时欢迎读者纠错和补充。
1.同一运算符中多个操作数的计算顺序(&&、||、?和,运算符除外)
例如:x = f()+g(); //错误
f()和g()谁先计算由编译器决定,如果函数f或g改变了另一个函数所使用变量的值,那么x的结果可能依赖于这两个函数的计算顺序。
参考: 《C程序设计语言(第2版)》 P43
2.函数各参数的求值顺序
例如: printf("%d,%d\n",++n,power(2,n)); //错误
在不同的编译器可能产生不同的结果,这取决于n的自增运算和power调用谁在前谁在后。
需要注意的是,不要和逗号表达式弄混,都好表达式可以参考这篇文章:c语言中逗号运算符和逗号表达式
参考: 《C程序设计语言(第2版)》 P43
3.通过指针直接修改 const 常量的值
直接通过赋值修改const变量的值,编译器会报错,但通过指针修改则不会,例如:
1
2
3
4
5
6
7
8
9
|
int main ( )
{
const int a = 1 ;
int * b = ( int * ) & a ;
* b = 21 ;
printf ( "%d, %d" , a , * b ) ;
return 0 ;
}
|
a输出值也由编译器决定。
19、struct | class | |
默认继承权限 | public | private |
默认数据访问控制 | public | private |
模板参数 | 不能定义 | 可以用于定义模板参数 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//预处理:处理#include、宏替换和条件编译
//编译:生成目标文件(.cpp->.o)
//链接:链接多个目标文件
//例子:
//main.cpp
int
main(){
fun();
}
//编译不可通过,提示函数fun()未声明
void
fun();
int
main(){
fun();
}
//编译可通过,链接不可通过,提示函数fun()未定义
|
(3) 对于复合的赋值运算符如+=、-=、*=、/=、&=、!=、~=、%=、>>=、<<=建议重载为成员函数。
(4) 对于其它运算符,建议重载为友元函数。
运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载。重载运算符的函数一般格式如下:
函数类型 operator 运算符名称 (形参表列)
{
对运算符的重载处理
}
重载为类成员函数时参数个数=原操作数个数-1(后置++、--除外)
重载为友元函数时 参数个数=原操作数个数,且至少应该有一个自定义类型的形参