初始化、赋值及内存模型

来源:互联网 发布:windows集中管理 编辑:程序博客网 时间:2024/04/30 12:48

        对于基本类型,初始化和赋值在语法上比较相像,功能通常也差别不大,例外情况是字符串。字符串在C语言中是个比较特殊的东西,有些特别的处理,C语言学习者通常要花很大精力来学习字符串的使用。对于字符数组,可以用初始化列表和字符串常量两种方式初始化,而后赋值却必须逐位操作,因此对于字符串,初始化和赋值至少在语法上是完全两样的。

C语言中不同变量和数据存储在不同的区域:

代码段  可执行代码、字符串常量 数据段  已初始化全局变量、已初始化全局静态变量、局部静态变量、常量数据 BSS段  未初始化全局变量,未初始化全局静态变量 栈  局部变量、函数参数 堆  动态内存分配 
        具体内容在此不详述,可以很方便地搜索到。

        对于复杂类型例如类,初始化和赋值也是不同的,它们的语义不同,初始化是构造一个新的对象,在初始化时,编译器知道要进行初始化的变量还没有被构造,明确知道这个变量现在的状态,就可以相对简单的对这个变量进行操作;而在赋值时,这个变量先前的状态是什么样的编译器并不清楚,于是就需要进行许多操作来做一些清理等方面的工作。

        例如百度百科string类词条:

class String{public:String(const char *str = NULL);// 普通构造函数String(const String &other); //拷贝构造函数~ String(void); //析构函数String & operator =(const String &other);//赋值函数private:char *m_data;// 用于保存字符串};//普通构造函数String::String(const char *str){if(str==NULL){m_data = new char[1]; // 对空字符串自动申请存放结束标志'\0'的//加分点:对m_data加NULL 判断*m_data = '\0';}else{int length = strlen(str);m_data = new char[length+1]; // 若能加 NULL 判断则更好strcpy(m_data, str);}}// String的析构函数String::~String(void){delete[] m_data; // 或delete m_data;}//拷贝构造函数String::String(const String &other) // 输入参数为const型{int length = strlen(other.m_data);m_data = new char[length+1]; //对m_data加NULL 判断strcpy(m_data, other.m_data);}//赋值函数String & String::operator =(const String &other) // 输入参数为const型{if(this == &other) //检查自赋值return *this;delete[] m_data; //释放原有的内存资源int length = strlen( other.m_data );m_data = new char[length+1]; //对m_data加NULL 判断strcpy( m_data, other.m_data );return *this; //返回本对象的引用}

        初始化时调用的是构造函数如String::String(const char *str),而赋值时调用的是String & String::operator =(const String &other),这两个函数主要的区别就是赋值前要先清理旧的数据。对于这个实现,差别还不是特别大,但已经可以看出初始化和赋值的主要不同了。在更复杂的类里,初始化和赋值所做的操作可能相差甚远。

       初始化和赋值还有一点不同,即初始化需要检查输入数据的合法性。初始化时,类的构造函数以某些数据作为参数构造对象时,要先检查这些数据(参数)是否合法;但在赋值时,左值和右值的对象都已构造完毕(或由编译器处理,例如常量字符串对象的构造),无须检查对象属性的合法性。按Bjarne的说法,“构造函数需要建立起这个类的不变式,其他函数可以依靠这个不变式,然而又必须维护它”。有过相关经验的人都知道,检查输入合法性之类保障程序健壮性的代码是很繁琐的,所以这是初始化和赋值的一个比较重要的区别。

       这篇文章只是点到即止,详细的知识都可以在网上搜到,由于某些原因就不展开了,下篇见~



0 0
原创粉丝点击