C++捉虫笔记

来源:互联网 发布:户型设计软件手机 编辑:程序博客网 时间:2024/04/28 07:59

《捉虫历险记—C++ bug大围剿》读书笔记

1.       你会用C++写正确Hello World 程序吗?

你认为你能吗?我写了一年多的程序,最初我认为我是可以的,但是当我看到错误的程序的时候,我却没发现那是个错误,原因只有一个,我对C++的函数的了解太肤浅了。

示例程序如下:

#include <iostream>

 

void main(void)

{

std::cout<<"Hello World/n";

}

你认为上面的程序是对的吗?至少我把它卸载IDE中,编译运行的时候,出现了正确的的输出结果,所以我认为是对的,其实不然。

原因:函数main()不是一个void型函数,而是一个int型函数。

正确的程序如下:

#include <iostream>

 

int main()

{

std::cout<<"Hello World/n";

return (0);

}

2.       静态变量和自动变量的区别

静态变量的生存期就是整个程序的运行期。在程序开始运行前就为其分配相应的存储空间,在程序的整个运行期间一直占用,直到结束。

自动变量的生存期是说明了自动变量的函数或分程序。它对存储空间的利用是动态的。其初值在每次为自动变量分配存储后都要重新设置。

示例程序:

#include <stdio.h>

 

//first--Demonstration of automatic variable.

int first(void)

{

int i = 0;  //Demonstration variable

return (++i);

}

 

//second--Demonstration of static variable

int second(void)

{

static int i = 0; //Demonstration variable

return (++i);

}

 

int main()

{

int counter;     //Call counter

 

for(counter=0; counter<3; counter++)

{

        printf("First %d/n",first());

}

 

for(counter=0; counter<3; counter++)

{

        printf("Second %d/n",second());

}

return (0);

}

结果输出:

3.       return (++i) return (i++)

return (i++)

(1) 保存i的值

(2) 递增i

(3) 返回已保存的值

return (++i)

(1) 递增i

(2) 保存i的值

(3) 返回保存的值

4.       典型的初始化问题

 

#include <iostream>

int main()

{

int sum;   //the running sum

int count; //the current number

for(count=1; count<=100; count++)

{

        sum += count;

}

 

std::cout<<"The sum of numbers"<<"between 1 and 100 is "<<sum<<'/n';

return (0);

}

 你认为上面的程序输出会是你想要的结果吗?也许吧,但机会太小了,由于初始化过程中对变量sum 没有做初始化,因此您不能指望没有初始化的变量,它可能包含任何值,所以输出结果也就可能是任何的值,正确的做法就是int sum = 0;

5.       行结束符对程序的影响

#include <iostream>

int main()

{

int result; //result of the addition

result = 2 + 2;

std::cout<<"the answer is "<<result;

std::cout<<"the answer is "<<result<<'/n';    //建议的写法

return (0);

}

作者对程序给出了这样的解释

MS-DOS中,您会得到如下结果:

The answer is 4C:>#

(#是光标)

UNIX系统中,您可能得到如下结果:

The answer is 4$ #

问题在程序员没有在std::cout语句的结束处加上行结束标志。结果就是:程序运行,输出一个语句,然后退出,而让光标停留在输出行的末尾位置。命令行处理器接着就继续运行,并在程序的输出内容之后输出其系统命令提示符(MS-DOSC:>UNIX$)

但我在自己机器上的执行并没有出现这样的结果,C:>始终也没有出现,我想惟一的解释就是后来的C++IDE做了改进 当你的输出结尾没有行结束符的时候自动加上。

6.       第一个内存泄露问题

这是我第一次接触到内存泄露的问题,以前只知道有这么回事,而且程序最要命的错误就是内存泄露,调试起来会很费劲,今天也算是初见端倪,看来以后真的防着这个家伙了,哈哈。

程序是这样的,输出1—5之间数字的平方仅此而已,看看下面的程序,是否满足你的要求呢?

#include <iostream>

int main()

{

int array[5];    //an array for the squares

int i; //index into the array

for(i=1; i<=5; i++)

{

        array[i] = i * i;

}

for(i=1; i<=5; i++)

{

        std::cout<<i<<" squared is "<<array[i]<<'/n';

}

return (0);

}

程序结果输出正确,但是会报要命的系统错误,如下图示:

其实原因很简单:

C++数值下标的基值是0。因此,数组array[5]的有效元素是:

array[0], array[1], array[2], array[3], array[4]

然而,程序员使用的元素是1-5。不存在元素array[5],因此,程序就修改了随机内存,导致内存泄漏。

这也是为什么C++程序不使用这样语句的原因:

for (i = 1; i <= 5; ++i) {

而是使用:

for (i = 0; i < 5; ++i) {

修改后的程序如下:

#include <iostream>

int main()

{

int array[5];    //an array for the squares

int i; //index into the array

for(i=0; i<5; i++)

{

        array[i] = (i+1) * (i+1);

}

for(i=0; i<5; i++)

{

        std::cout<<i+1<<" squared is "<<array[i]<<'/n';

}

return (0);

}

7.       用字符变量表示数字的时候要多加小心。它们可能达不到您想要的结果。

比如如下程序,你认为输出是什么呢?

#include <iostream>

int main()

{

char ch;  //the flag

ch = 0xFF;     //set the flag

 

//check the flag

if(ch == 0xFF)

{

        std::cout<<"Sucessed/n";

}

else

{

        std::cout<<"Fails/n";

}

return (0);

}

或许你认为肯定是Sucessed,但输出的缺失Fails,原因是这样的:ch可能是一个有符号的字符。这意味着,如果ch0xFF,则当它为了比较而转换为有符号整数的时候,您会得到int(ch)=-1(0xFFFFFFF)。这不是0xFF,导致比较失败。

原创粉丝点击