c++学习笔记(1.c到c++的升级)

来源:互联网 发布:魔方矩阵 编辑:程序博客网 时间:2024/04/29 03:01

本节知识点:

1.c++与c语言关系是包容的,不是对立的,c++继承了c的所有特性。c语言注重程序的运行效率,c++更注重程序的运行效率与开发效率的统一。本节我们就说说一些c++对c的加强。

2.变量定义的位置

    c语言中变量的定义必须在作用域开始的位置。

    c++只要在使用这个变量的前面进行定义就可以了。如下代码:

#include <stdio.h>int main(int argc, char *argv[]){    int c = 0;            for(int i=0; i<10; i++)    {        for(int j=0; j<10; j++)        {            c += i * j;        }    }    for(int i = 0; i<10; i++)    {        printf("hhh!\n");    }        printf("c = %d\n", c);      return 0;}

对于上面的代码:如果是c语言必须要把i,j,c的定义都放在作用域的开始位置,即放在使用i,j,c变量的前面,而c++不必这样。在那使用,在那定义,很方便,不容易把自己弄混。最好的一点是,在for循环结束后i和j局部变量是会被释放的,因为作用域结束了,减少内存开销,在下次使用for循环的时候依然可以使用i和j为变量名。

3.c++中的register属性

   c++中依然保留register属性,主要是为了兼容c语言。c++编译器有自己的优化方式,不使用register也可以优化。主要的区别是,在c语言中是不能对register修饰的变量进行取址运算。在c++中可以,一旦对于一个register修饰的变量进行了取址运算,register属性就无效了,这个变量就变成了普通变量了。代码如下:

#include <stdio.h>int main(int argc, char *argv[]){    register int c = 0;            printf("&c = %08X\n", &c);        return 0;}

4.多个同名全局变量问题:

    c语言中有一个小问题:就是可以定义多个同名变量。但是只能给其中的一个变量赋初值。

#include <stdio.h>int g_var;int g_var = 1;int main(int argc, char *argv[]){       return 0;}

    如上这段代码,在c语言中是合法的,g_var的定义可以在不同的文件中。但是只能有一处给赋初值,不然也会报错!!!其实在c语言中多个同名的全局变量最终也会被连接到静态存储区的同一个地址空间上去,即这些同名的全局变量仅仅开辟了一个存储空间,并且仅仅给了一个初值。其实这样看这个问题是不影响编程的,但是降低了代码的可读性和规范性。

    c++中是不允许定义多个同名的全局变量的。
5.c++中的const:

    在c++中,const修饰的不再是只读变量了,而是真正的常量了,因为不管怎么样都改变不了const修饰的变量了!因为c++中把const声明的变量,放在了符号表中了,当编译器遇到这个变量的时候,直接从符号表中进行替换。只有编译器发现对const使用了extern(对于全局变量的声明)或者&运算的时候,在给这个变量在内存中分配存储空间,但是一定要记得这个存储空间,你是可以看见地址,但是这个变量不存储在这个内存中,而是存储在符号表中。这是与c语言最不一样的地方,c语言中cosnt修饰的叫只读变量,是可以通过地址或指针对这块内存进行修改的(因为这个值就存在这块内存中,改了内存就可以了),不涉及符号表的问题。所以说c++中const是真正的常量,无论你怎么样都改变不了的。代码如下:

#include <iostream>#include <stdio.h>int main(int argc, char *argv[]){const int a =10;printf("%p\n",&a);printf("%d\n",a);*(int* )((unsigned int)(0x22ff4c)) = 12;printf("%d\n",a);printf("%d\n",*(int* )((unsigned int)(0x22ff4c)));return 0;}

可以把上面的代码分别在c和c++的编译器中运行看看。

     const与#define的比较:相同点,两者都是常量,十分类似。不同点,const是在编译的时候,通过编译器处理的,#define是在预编译期间,简单的无脑替换的。const提供了类型的检查和作用域的检查,比#define更加安全。#define是没有类型的,并且要想设置作用域也得借助#udef宏,不是很方便。
6.c++中的struct::

     在c语言中struct定义的是一组变量的集合,c语言编译器并不认为这是一种新的类型。

     在c++中,把struct当作一个新类型的定义声明,其实个人觉得应该是包含了typedef的功能在里面了!

7.c++中对类型的限定:

     在c++中弥补了c语言的一个重大缺陷,就是c语言中有好多默认类型,比如:函数如果不声明返回值类型,默认的类型是int。对于g()这样一个没有定义参数的函数,在调用的时候可以传递任意个参数等。这些都是c的垃圾特性。

    在c++中,对类型的检查是十分严格的。

    a.所有的函数和变量都必须有类型。

    b.对于int f()这样的函数,为了兼容c语言,c++并没有报错处理,仅仅是把这种类型的函数,变成了int f(void)这样的函数(没有参数的函数),确保不能传递任意个参数。

    c.还有就是c++,要保证赋值运算(=号),两边的类型必须要相同,不然会报错的。在c语言中是不会,仅仅是给个警告,然后进行隐式转换。c++避免了这种隐式转换带来不必要的bug,如果一定想赋值就要进行强制类型转换。

    d.在c语言中int  f(),表示接受任意参数的函数,int  f(void),表示无参数的函数。在c++中int f()和int f(void)没有任何区别,都表示无参数的函数。

8.补充(本节有两个问题要补充,都是c语言的问题):

    第一个问题是:const int a; 和  int  b;  两者不是一个类型。要想定义一个指针去指向a,就要这样:

int *p = (int* )&a;

要对&a进行强制类型转换的,因为&a是一个const  int *的指针,跟int* 不一样。

要不就这样:

const int *p = &a;

类型也匹配了,并且const  int *p还能保证*p的值不能改变,也符合const  int  a的意图。

    第二个问题是:typedef 定义的类型是一个整体不能拆开看的。

比如说:

#include <stdio.h>#include <stdlib.h>typedef  int*  intp;int main(){int a; int q = 10; const intp b=&a;   *b = 123; intp const c = &a;*c  = q;return 0;}

对于上面的代码,千万不能把intp 拆开来看,当作int* 看。因为typedef是把已有的类型重新定义。这个时候int*  就是一个类型了。const intp 跟intp const是一样的了。都是intp这个类型不能改变,即int* 这个类型不能改变,int*是一个指针类型,果断是指针不能改变,所以说上面的代码是可以运行通过的。因为代码是对值进行改变。其实当intp变成一个整体的时候,const intp和intp const  就已经跟 int const  和const int是一样的了。
9.反思:通过对c++与c的对比学习,想到一个问题,就是对于这两种语言的学习,我觉得还是应该先学C,然后找到C的问题(产生C++转变的原因),再转向C++,然后对比学习,这样就可以抓住两者的优缺点,使用方向即特性。还有一个是应该十分注意的,就是学C语言就用c语言的编译器(如:gcc),学c++就用c++的编译器(如:g++)。极其不推崇学c语言的时候使用VC6.0或者是VS等c++的编译器。这样很容易弄混c的特性和c++的特性。


课后补充:

 1.对const关键字另一用法的补充:对于类的成员函数,可以使用const关键字声明为常成员函数,即void fun()const ;  所谓常成员函数就是不改变成员变量值的函数,也不调用非常成员函数。如果常成员函数中,有改变成员变量的值的语句,就会报错!

  示例代码如下:

#include <iostream>using namespace std;class test{public:int a;int b;void fun()const //此为常成员函数 {cout << a << endl;cout << b << endl;} void put(){a = 12;b = 120;}};int main(){test t1;t1.put();t1.fun(); }



 

原创粉丝点击