关于C++变量初始化的总结(转载+自己总结)

来源:互联网 发布:交换机更换网络 编辑:程序博客网 时间:2024/04/30 07:34

         当定义没有初始化的变量时,系统有可能会为我们进行隐式的初始化,至于系统是否帮我们隐式初始化变量,以及为变量赋予一个怎么的初始值,这要取决于该变量的类型以及变量的定义域

1.内置类型变量的初始化 

内置变量是否自动初始化,取决于该变量的定义域。

①在全局范围内的内置类型变量均被编译器自动初始化为0

#include<iostream>using namespace std;//全局范围内的部分内部变量int gi;  //被自动初始化为0float gf;  //被自动初始化为0.0double gd;  //被自动初始化为0.0char gc;  //被自动初始化为'\0'int main(int argc, char **argv){  return EXIT_SUCCESS;}

②在函数体内定义的内置类型变量值随机(有的编译器可能会为你初始化为0,但千万别依赖于这种可能行为,因为它会给你的程序带来未定义的行为

#include<iostream>using namespace std;int main(int argc, char **argv){  //局部范围内的部分内部变量  int i;  //不被自动初始化,值随机(有可能是0,依编译器实现而定)  float f;  //不被自动初始化,值随机(有可能是0,依编译器实现而定)  double d;  //不被自动初始化,值随机(有可能是0,依编译器实现而定)  char c;  //不被自动初始化,值随机(有可能是0,依编译器实现而定)  return EXIT_SUCCESS;}

③内置类型数组的初始化规则同上

#include<iostream>using namespace std;//全局范围内的内置类型数组int gIntArr[5];  //5个元素都被初始化为0int main(int argc, char **argv){  //局部范围内的内置类型数组  int intArr[5];  //未被初始化    return EXIT_SUCCESS;}

这里需要特别强调一点,数组初始化如下:

char str[10];//没初始化的for(int idx=0;idx<10;idx++){std::cout<<(int)str[idx]<<' ';}std::cout<<std::endl;memset(str,0,sizeof(str)); //初始化后的for(int idx=0;idx<10;idx++){std::cout<<(int)str[idx]<<' ';}std::cout<<std::endl;char str1[10] = "";char str2[10] = {};//VC++6.0下报错,不支持这种语法char str3[10] = {0};for(int idx=0;idx<10;idx++){std::cout<<(int)str1[idx]<<' ';}std::cout<<std::endl;for(int idx=0;idx<10;idx++){std::cout<<(int)str2[idx]<<' ';}std::cout<<std::endl;for(int idx=0;idx<10;idx++){std::cout<<(int)str3[idx]<<' ';}std::cout<<std::endl;system("pause");

输出结果

-52 -52 -52 -52 -52 -52 -52 -52 -52 -520 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0Press any key to continue . . .

char buffer[260]="";char buffer[260]={0};memset( buffer, 0, sizeof(buffer)/sizeof(char));

所以以上三种是等效的,个人比较习惯memset,这种是直接操作内存的,而其他方法大多数都是依赖系统或者编译器的。

CString初始化  CString str;  str = "";  如果是多字节str = _T(""); 清空str.Empty();

值得注意的是:

char buffer[4];memset(buffer,0,sizeof(char)*4);strcpy(buffer,"123");//"123"中最后隐藏的'\0'占一位,总长4位。

这里的memset是多余的. 因为这块内存马上就被全部覆盖,清零没有意义.
另:以下情况并不多余,因某些编译器分配空间时,内存中默认值并不为0:
char buffer[20];memset(buffer,0,sizeof(char)*20);memcpy(buffer,"123",3);//这一条的memset并不多余,memcpy并没把buffer全部覆盖,如果没有memset,//用printf打印buffer会有乱码甚至会出现段错误。//如果此处是strcpy(buffer,"123");便不用memset,//strcpy虽然不会覆盖buffer但是会拷贝字符串结束符
这种情况如果没有memset将buffer初始化为0的话,copy过后的buffer肯定会有乱码

memset可以方便的清空一个结构类型的变量或数组。

  如:

   

  struct sample_struct  {        char csName[16];        int iSeq;        int iType;  };

  对于变量

  struct sample_strcut stTest;

  一般情况下,清空stTest的方法:

  stTest.csName[0]='/0';

  stTest.iSeq=0;

  stTest.iType=0;

  用memset就非常方便:

  memset(&stTest,0,sizeof(struct sample_struct));

  如果是数组:

  struct sample_struct TEST[10];

  则

  memset(TEST,0,sizeof(struct sample_struct)*10);

memset()的深刻内涵:用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为‘memset(a, '/0', sizeof(a));

  memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),会造成b的内存地址溢出。

  strcpy就只能拷贝字符串了,它遇到'/0'就结束拷贝;例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字符串长度(第一个‘/0’之前)是否超过50位,如超过,则会造成b的内存地址溢出。

2.类类型变量的初始化

    类类型变量是通过构造函数进行初始化的,不论类类型变量在哪里(全局或者局部)定义,该类类型变量的构造函数(默认构造函数或者指针的参数构造函数)总会被调用。

     想要知道构造函数在各种情况下如何初始化类中数据成员的,我们必须首先了解构造函数的初始化发生在何时?

//构造函数中的初始化发生在构造函数的初始化列表中//而非构造函数体中class Foo{  public:    Foo(int i):_integer(i)  //初始化列表中进行的是初始化    {      //这里是构造函数的函数体      //在这里进行的是赋值操作,而不是初始化      _integer = i;    }  private:    int _integer;};

既然构造函数的初始化是发生在初始化列表中的,那么,对于初始化列表中没有显示进行初始化的内置类型变量来说,其初始化规则就与上述内置变量的规则相同了。

#include<iostream>using namespace std;class Foo{  public:    Foo(void):_explicitInit(1024){}  private:    int _explicitInit;  //在构造函数初始化列表中                        //显式初始化的内置类型变量    int _implicitInit;  //没有在构造函数中显式初始                        //化的内置类型变量};Foo gF;  //全局范围内的类类型变量,_explicitInit被         //显式初始化为1024,_implicitInit被自动初始         //化为0int main(int argc, char **argv){  Foo f; //局部范围的类类型变量,_explicitInit被         //显式初始化为1024,_implicitInit不会被         //自动初始化,值随机  return EXIT_SUCCESS;}

C++的类中内置类型的成员变量的初始化:


//test.hclass test{       private:int a;//普通成员const int b;//常量成员static int c;//静态成员static const int d;//静态常量成员int &e;//引用类型成员};

成员变量的初始化有且仅有两种:

1)用“=”赋值

2)用成员初始化列表

记住一点:只能用成员初始化列表有两类:常量成员(注意没有静态常量成员)和引用类型成员。

再记住一点:静态成员和静态常量成员由于是类共有的,不是属于某一个对象的,因此不能再构造函数中初始化。

最后记住一点:静态成员(这里不包括静态常量成员)必须在类外初始化。

最后的最后记住一点:引用变量必须初始化后才能使用。

class test{//int a=1;//错误:对象没有构造,尚未分配内存空间int a;const int b;//static int c=1;//错误:不可以在声明时初始化static int c;const static int d=1;//唯有该类型可以这样int &e;//引用类型必须用成员初始化列表public:test(int _e):b(1),e(_e)/*引用初始化必须为左值*/{}};int test::c=1;const int test::d=1;//也可以这样初始化
//test.hclass test{public:       test();       test(int _e);       ~test();private:int a;//普通成员const int b;//常量成员static int c;//静态成员static const int d;//静态常量成员int &e;//引用类型成员};

//test.cpp//静态成员变量以及const静态成员变量int test::c = 1;const int test::d = 1;test::test(){}test::test(int _e)       :a(1),e(_e)  //引用初始化必须为左值{}test::~test(){}








0 0
原创粉丝点击