C++易错点总结
2015-03-17 20:43
197 查看
1.下面这段代码考察变量的作用域问题。
[cpp] view
plaincopy
#include<iostream>
using namespace std;
void other()
{
static int a = 2;
static int b;
int c = 10;
a += 2;
c += 5;
cout<<"----other-----"<<endl;
cout<<a<<" "<<b<<" "<<c<<endl;
b = a;
}
int main()
{
static int a;
int b= -10, c= 0;
cout<<"----main-----"<<endl;
cout<<a<<" "<<b<<" "<<c<<endl;
c += 8;
other();
cout<<"----main-----"<<endl;
cout<<a<<" "<<b<<" "<<c<<endl;
other();
return 0;
}
答案如下:
----main-----
0 -10 0
----other-----
4 0 15
----main-----
0 -10 8
----other-----
6 4 15
考察点:
局部作用域中静态变量的特点是,它并不会随着每次函数调用而产生一个副本,也不会随着函数返回而失效。也就是说,当一个函数返回后,下一次再调用时,该变量还会保持上一回的值,即使发生了递归调用,也不会为该变量建立新的副本,该变量会在每次调用见共享。
解析:
第一次a=0,b=-10,c=0,之后调用other函数,因为a和b为静态局部变量,所以在other函数就有保持值的特点,这时,根据就近原则,a=4,b=0,c=15.
然后继续执行,发现a,b的改变都是在other中,而对main中的a,b没有影响,所以a,b值不变,c由于自加8,所以c=8.然后又进入other,因为a,b为局部静态变量,不会再每次进入相同函数时产生副本,所以进入时a=4,自加2,等于6,上次函数结束时b=a,所以b=4,这次再进入时b还是保持4不变,而c是动态局部变量,每次进入函数都要重新初始化,所以c=10,自加5等于15.所以a=6,b=4,c=15.
2.说明Arr类中,element元素返回一个引用对象的原因。
[cpp] view
plaincopy
#include<iostream>
#include<cstdio>
#include<cassert>
using namespace std;
class Point
{
private:
int x, y;
public:
Point():x(0), y(0)
{
cout<<"default called"<<endl;
}
Point(int x, int y):x(x), y(y)
{
cout<<"not default called"<<endl;
}
~Point(){cout<<"destructor called"<<endl;}
int getx()const{return x;}
int gety()const{return y;}
void move(int newx, int newy)
{
x = newx;
y = newy;
}
};
class Arr
{
private:
Point *p;
int size;
public:
Arr(int size):size(size)
{
p = new Point[size];
}
~Arr()
{
cout<<"deleting"<<endl;
delete []p;
}
Point &element(int index)
{
assert(index >= 0 && index < size);
return p[index];
}
};
int main()
{
int count;
cin>>count;
Arr points(count);
points.element(0).move(5, 0);
points.element(1).move(5, 2);
return 0;
}
答案:
因为我们创建的points对象是一个在类内部由动态数组实现的对象,而我们对数组的操作无非就是取元素,改变元素,如果element不返回一个引用时,那么我们可以认为这个元素是只读的,我们无法通过赋值等途径改变这个元素(其实是一个对象)的值,而我们返回一个引用的话,就相当于取出元素本身,就可以对它进行正常的读写操作。这样才符合数组的性质。
3.浅复制和深复制
[cpp] view
plaincopy
#include<iostream>
using namespace std;
class A
{
private:
int len;
char *str;
public:
A(int length, char *s)
{
len = length;
str = new char[length];
strcpy(str, s);
}
A(const A &p) //浅复制就是注释掉自定义复制拷贝函数(试试看?)
{
len = p.len;
str = new char[p.len]; //深复制
strcpy(str, p.str);
}
~A()
{
delete str;
}
void show()
{
cout<<str<<endl;
}
};
int main()
{
A a(10, "hello");
A b = a;
b.show();
return 0;
}
4.看看下面这个代码怎么错了?
[cpp] view
plaincopy
#include<iostream>
using namespace std;
#define MAX 255
int main()
{
char p[MAX+1];
unsigned char ch;
for(ch=0;ch<=255;++ch)
{
p[ch]=ch;
cout<<ch<<"";
}
p[255]='\0';
cout<<ch<<endl;
}
错误在于ch<=255,这个条件。因为ch是unsigned char类型的,占据一个字节,所以最大值为255.当ch循环到255时候+1之后溢出,就变成0了。这样,就陷入了死循环。正确该法是ch<255.
[cpp] view
plaincopy
#include<iostream>
using namespace std;
void other()
{
static int a = 2;
static int b;
int c = 10;
a += 2;
c += 5;
cout<<"----other-----"<<endl;
cout<<a<<" "<<b<<" "<<c<<endl;
b = a;
}
int main()
{
static int a;
int b= -10, c= 0;
cout<<"----main-----"<<endl;
cout<<a<<" "<<b<<" "<<c<<endl;
c += 8;
other();
cout<<"----main-----"<<endl;
cout<<a<<" "<<b<<" "<<c<<endl;
other();
return 0;
}
答案如下:
----main-----
0 -10 0
----other-----
4 0 15
----main-----
0 -10 8
----other-----
6 4 15
考察点:
局部作用域中静态变量的特点是,它并不会随着每次函数调用而产生一个副本,也不会随着函数返回而失效。也就是说,当一个函数返回后,下一次再调用时,该变量还会保持上一回的值,即使发生了递归调用,也不会为该变量建立新的副本,该变量会在每次调用见共享。
解析:
第一次a=0,b=-10,c=0,之后调用other函数,因为a和b为静态局部变量,所以在other函数就有保持值的特点,这时,根据就近原则,a=4,b=0,c=15.
然后继续执行,发现a,b的改变都是在other中,而对main中的a,b没有影响,所以a,b值不变,c由于自加8,所以c=8.然后又进入other,因为a,b为局部静态变量,不会再每次进入相同函数时产生副本,所以进入时a=4,自加2,等于6,上次函数结束时b=a,所以b=4,这次再进入时b还是保持4不变,而c是动态局部变量,每次进入函数都要重新初始化,所以c=10,自加5等于15.所以a=6,b=4,c=15.
2.说明Arr类中,element元素返回一个引用对象的原因。
[cpp] view
plaincopy
#include<iostream>
#include<cstdio>
#include<cassert>
using namespace std;
class Point
{
private:
int x, y;
public:
Point():x(0), y(0)
{
cout<<"default called"<<endl;
}
Point(int x, int y):x(x), y(y)
{
cout<<"not default called"<<endl;
}
~Point(){cout<<"destructor called"<<endl;}
int getx()const{return x;}
int gety()const{return y;}
void move(int newx, int newy)
{
x = newx;
y = newy;
}
};
class Arr
{
private:
Point *p;
int size;
public:
Arr(int size):size(size)
{
p = new Point[size];
}
~Arr()
{
cout<<"deleting"<<endl;
delete []p;
}
Point &element(int index)
{
assert(index >= 0 && index < size);
return p[index];
}
};
int main()
{
int count;
cin>>count;
Arr points(count);
points.element(0).move(5, 0);
points.element(1).move(5, 2);
return 0;
}
答案:
因为我们创建的points对象是一个在类内部由动态数组实现的对象,而我们对数组的操作无非就是取元素,改变元素,如果element不返回一个引用时,那么我们可以认为这个元素是只读的,我们无法通过赋值等途径改变这个元素(其实是一个对象)的值,而我们返回一个引用的话,就相当于取出元素本身,就可以对它进行正常的读写操作。这样才符合数组的性质。
3.浅复制和深复制
[cpp] view
plaincopy
#include<iostream>
using namespace std;
class A
{
private:
int len;
char *str;
public:
A(int length, char *s)
{
len = length;
str = new char[length];
strcpy(str, s);
}
A(const A &p) //浅复制就是注释掉自定义复制拷贝函数(试试看?)
{
len = p.len;
str = new char[p.len]; //深复制
strcpy(str, p.str);
}
~A()
{
delete str;
}
void show()
{
cout<<str<<endl;
}
};
int main()
{
A a(10, "hello");
A b = a;
b.show();
return 0;
}
4.看看下面这个代码怎么错了?
[cpp] view
plaincopy
#include<iostream>
using namespace std;
#define MAX 255
int main()
{
char p[MAX+1];
unsigned char ch;
for(ch=0;ch<=255;++ch)
{
p[ch]=ch;
cout<<ch<<"";
}
p[255]='\0';
cout<<ch<<endl;
}
错误在于ch<=255,这个条件。因为ch是unsigned char类型的,占据一个字节,所以最大值为255.当ch循环到255时候+1之后溢出,就变成0了。这样,就陷入了死循环。正确该法是ch<255.
相关文章推荐
- C++基础知识易错点总结(1)
- C++基础知识易错点总结(3)
- C/C++易错点 总结
- C++基础知识易错点和易混淆总结汇总(不定时更新)
- C++易错点总结
- C++基础知识易错点总结(2)
- C++基础知识易错点总结(2)
- c,c++易错点总结之递归,循环
- C++基础知识易错点总结(1)
- C++中的引用总结
- C++中的static关键字的总结
- C++学习总结_为什么要使用指针
- C++开源库学习地址总结
- c/c++中的static关键字总结
- 排列组合算法总结(基于C++实现)
- 关于C++ const 的全面总结
- 对C++中string类型的总结
- 软件开发常用设计模式—单例模式总结(c++版)
- C++第三章总结
- C++中的函数指针和函数对象总结