1、关于指针分配内存的题目:
void GetMemory(char *p)
{
p = (char *)malloc(12);
}
int main(void)
{
char *str = "Hello";
GetMemory(str);
strcpy(str,"Hello World");
printf("%s",str);
return 0;
}
这个题目在VS2010下是运行时报错,首先忽略malloc(11)本身就放不下"Hello World"的问题,关键str是个const char*,因为其指向的是"Hello",人家是存在静态常量存储区的,所以是不可以将str作为strcpy的第一个参数的,若是char str = “Hello”;则是可以的;其次,GetMemory函数没有起到为str分配内存的作用,因为传进去的是str,而并非str的地址,所以在GetMemory中对p的操作并没有真正改变str,so程序应该改成:
void GetMemory(char **p)
{
*p = (char *)malloc(12);
}
int main(void)
{
char *str = "Hello";
GetMemory(&str);
strcpy(str,"Hello World");
printf("%s",str);
return 0;
}
2、关于数组名字做左值的问题
void main()
{
char s[] = "abcde";
s += 2; //编译错误
printf("%c\n",s[0]);
}
数组和指针的一个很重要的区别就是数组名字是不能改变的,即不能做左值,so将char s[]改成char* s就OK了。
3、二维数组的存储方式
int main(void)
{
char matrix[3][3]={{'a','b','c'},{'d','e','f'},{'g','h','i'}};
printf("%c",matrix[1][4]);
return 0;
}
二维数组分行优先和列优先两种存储方式,在C++中是采用行优先的,所以第i+1行是紧接着第i行线性存储的,所以输出的是h。
4、C++的析构函数为虚函数
记住:构造函数不能是虚函数!
经常遇到的题目,特别是选择题问输出结果的,有一句话很重要:如果基类存在虚函数,那么析构函数必须为虚函数!!
当基类指针指向子类的对象时,若析构函数不是虚函数,则最后只调用基类的析构函数,这会造成内存泄露!
2014.05.12
果然没事看CSDN牛人的博客是受益匪浅的,最近看STL的时候无意中看到:
其中实在不明白最后三组的结果:
- const int x = 50;
- int* y = (int *)(&x); // 同样的地址,但是内容是不一样的
- *y = 200;
- cout << "x: "<<x<<" address: "<<&x<<endl;
- cout << "*y: "<<*y<<" address: "<<y<<endl;
- cout<<endl;
- const int xx = 50;
- int* yy = const_cast<int *> (&xx); // 同样的地址,但是内容是不一样的
- *yy = 200;
- cout << "xx: "<<xx<<" address: "<<&xx<<endl;
- cout << "*yy: "<<*yy<<" address: "<<yy<<endl;
- cout<<endl;
- // int
- const int xxx = 50;
- int yyy = const_cast<int&> (xxx); // yyy是另外一个int对象
- yyy = 200;
- cout << "xxx: "<<xxx<<" address: "<<&xxx<<endl;
- cout << "yyy: "<<yyy<<" address: "<<&yyy<<endl;
单步跟踪发现x的值确实发生了变化,但是为什么输出结果就是不对呢,在实验室同学的提醒下发现,万恶的编译器又进行了优化,故在const int x前加了volatile,当然最终x的值也是200了,但是输出的地址就是1,这就牵扯到另外一个知识了:ostream的operator<<有哪些:
ostream 有 operator<<(const void*) 但是没有operator<<(volatile void*), 当 cout<<&x 时, 因为 &ix的类型是 volatile const int *,没有对应的operator<<(valatile int*)。
解决办法就是使用const_cast,这个强制转换符是专门用于const和volatile的,故:
cout<<const_cast<int*>(&x);
但是又牵扯另一个问题了:char*
operator<<会把char*类型当成要输出字符串,例如:
char* str = "aa";
cout<<str<<endl;
结果就输出: aa
故再次使用强制转换符:reinterpret_cast
cout<<reinterpret_cast<void *>(&str)<<endl;
输出结果:0012FE2C
在这其中,要注意以后书写输出时最后最好加endl,因为可以刷新输出,使结果立马显示到控制台。
言归正传,那这个编译优化叫什么呢?常量重叠:
所有用使用const 常量的地方将直接在编译时期替换成其对应的字符值。但常量有自己的内存,只是编译器优化了不知从内存中取值,而是直接是进行值代换。
若想摆脱这种命运,还是尽量少用这些个强制类型转换符吧!
最近看到了一个面试题,const在C++中的机制,所以对const又做了几个实验:
const int f = 10;
int main ()
{
int* p = const_cast<int*> (&f);
*p = 20;
cout<<*p<<f<<endl;
return 0;
}
当f是全局变量时就无法进行修改,当定义为局部变量时还是在栈上,可以通过指针修改,但编译器只在预处理时读一次值,之后偷懒。
如果是结构体类型的数据,编译器就不会做这种优化,因为不是内置类型,不知道如何替换。
int main ()
{
struct test{
int a;
test()
{
a = 5;
}
};
const test f;
int* p = const_cast<int*> (&f.a);
*p = 20;
cout<<*p<<f.a<<endl;
return 0;
}
输出结果:2020
2014.05.19
最近出差,木有好好学习,要好好准备软考!
虚函数一定是public的,不然编译都通不过。。。