理解对象的构造时发生的情况

来源:互联网 发布:嵌入式linux系统裁剪 编辑:程序博客网 时间:2024/04/27 22:11

当一个对象被创建时,会发生什么情况呢?

例如:

template<typename T>

class boy{

    public:

        boy(const string &new_name, T *ptr){

                  name  = newname;

                   adress = ptr;

        }

       ......

    private:

        sting name;

        T *adress;

}

 

对于上述这个类而言,当我们在某处执行 :

string *n_ptr = &n_adress;//一个之前被定义的string对象

boy<srting> *jerry = new boy("jerry", n_ptr);

此时会发生以下几件事:

1.编译器根据模板实例化一个boy<string>类,并生成相关的函数,这将在编译期完成。

2.对于new boy("jerry", n_ptr);编译器会根据字符串字面值生成一个临时对象,然后下面的语句将变成:

   string _temp("jerry");//这里会调用string对象的构造函数。

   boy<string> *jerry = new boy(_temp, n_ptr);

3.new 运算符会调用operator new标准库函数为对象分配空间,然后调用对象的构造函数。

4.在operator new 分配空间后,编译器还要保证完成一件事情,那就是为生成boy<string>对象而首先对该对象的各个数据成员

   进行初始化。于是这里相对应boy<string>类有两个数据成员,一个时string类得对象,一个是T类(即string类)的指针。对string类

  成员的初始化会调用string类得默认构造函数,于是,编译器在这里会生成调用string、类构造函数的代码插入到代码片段中。

5.执行boy<string>类得构造函数,即执行函数体,而在函数体中,又有两个赋值语句:

   name = new_name;

   adress = ptr;

   从第一个赋值语句可以看出,这里又调用了以此string对象的operator =,于是,上面的那次默认构造函数的调用完全是多余的。

 

而当我们将类改写成:

 

template<typename T>

class boy{

    public:

        boy(const string &new_name, T *ptr):name(new_name),adress(ptr){

          }

       ......

    private:

        sting name;

        T *adress;

};

这时,我们所做的工作就简单的多,成员初始化列表完成的功能只有一件事:告诉编译器,我们将如此初始化我们的成员,

于是,当new操作符调用operator new 分配完对象的内存空间后,编译器会把string对象的拷贝构造函数安插到代码中,以完成

对象的初始化工作,而构造函数的函数体内,什么都不做,这样,我们编制调用了一次构造函数,这便是效率的体现。

 

原创粉丝点击