C++构造函数深度学习

 更新时间:2016年08月13日 11:40:20   作者:郭小雷  
这篇文章主要为大家详细介绍了C++构造函数,深度学习C++构造函数,感兴趣的小伙伴们可以参考一下

本文针对C++构造函数进行深度探究,供大家参考,具体内容如下

1、引子: 
以下代码中的输出语句输出0吗,为什么?

struct Test
{
  int _a;
  Test(int a) : _a(a) {}
  Test()
  {
    Test(0);

  }

};
Test obj;
cout << obj._a << endl; 

输出为:-858993460

2、剖析
上面代码的输出为一个垃圾值,也就是说obj调用构造函数并没有对成员进行初始化工作,虽然默认无参构造Test()内部调用了Test(int a),但从结果看,初始化工作并不成功。这是为什么呢? 

在执行构造函数时,Test()并不会调用"this"对象(即obj对象)的Test::Test(int a),而是会用Test::Test(int a)来创建一个新的临时实例对象,然后当这条语句执行完后,这个新的临时对象马上就会被销毁。这样一来,"this"对象就没有被初始化,成员_a就是垃圾值,以后使用"this"对象就有可能产生一些问题。

3.重点:构造函数互相调用
 分析完这个题目之后,我们会想到另一个问题。也是我们今天重点关注的问题:

class Test
{ 
  int _a; 
  int _b; 
  int _c; 

public:

  Test(int a, int b) : _a(a), _b(b),_c(0) {} 

  Test(int a, int b, int c); 

}; 

如果我们C++类中有两个构造函数,分别为Test(int a, int b)和Test(int a, int b, int c)。如果我们的构造函数Test(int a, int b, int c)要完成所有成员(a,b,c)的赋值初始化工作,可以这样写:

Test::Test(int a, int b, int c)  

  : _a(a)

  , _b(b)

  , _c(c)

{ 

} 

但是,这样写又重复了构造函数Test(int a, int b)的工作,类成员少的情况下还好,如果成员非常多,重复写的话代码量过大,而且代码可读性降低了。然而我们可以看到构造函数Test(int a, int b)已经完成了成员a和成员b的赋值初始化工作,为了减少代码量,就想着让3个参数的构造函数调用2个参数的构造函数,然后在执行一些自己的代码,这就如同派生类先调用基类的同名函数,再执行自己特有的代码。但是这种机制如何实现呢? 

之前我们得出过结论:构造函数调用另一个构造函数并不能完成当前对象的初始化工作,只是初始化了临时对象。下面我们就进入本文的核心问题:如何在构造函数中调用本类的另一个构造函数来初始化当前对象?

方法一:使用placement new技术,在3个参数中显式调用2个参数的构造函数。
3参数构造函数可以这样实现:

Test::Test(int a, int b, int c)  
{ 
  new (this) Test(a, b); 
  ... 

} 

构造函数分为2个执行阶段:一是在初始化列表的初始化阶段,二是在构造函数体内的赋值阶段。上述方法是在第二个阶段调用2个参数的构造函数。 

placement new是operator new的一个重载版本,只是我们很少用到它。如果你想在已经分配的内存中创建一个对象,使用new是不行的。也就是说placement new允许你在一个已经分配好的内存中(栈或堆中)构造一个新的对象。原型中void*p实际上就是指向一个已经分配好的内存缓冲区的的首地址。placement new技术的形式是 new(void *p) Type(...),表示在p所指的内存区域调用Type构造函数,该过程没有内存请求。 

这个方法本质就是在对象地址处,调用2个参数的构造函数重新生成一个新的对象然后覆盖该对象。这个实现方法有投机取巧的嫌疑。 

方法二:使用C++11新特性——委托构造函数(Delegating constructors)。可以在构造函数初始化列表直接调用,类似于调用基类构造函数。

Test::Test(int a, int b, int c) : Test(a, b) 
{ 

  ... 

} 

上述说了构造函数有2个执行阶段,该方法是在第一个阶段进行的,更加方便。但是注意不能在Test(a, b)后面在接_c(c)了,因为调用2个参数的构造函数之后,就相当于该对象已经初始化完成了,不能在初始化列表放入其他成员的初始化形式。只能放在构造函数体中的赋值阶段。该方法目前只能用在VS2013中。 

这个方法利用了C++11标准中的新特性——委托构造函数(Delegating constructors)。目前只能再VS2013及以上的版本使用,这个方法局限性很大,不过确实很方便。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • C++简易版Tensor实现方法详解

    C++简易版Tensor实现方法详解

    这篇文章主要介绍了C++简易版Tensor的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值
    2022-08-08
  • C++实现Matlab的zp2tf函数的示例代码

    C++实现Matlab的zp2tf函数的示例代码

    matlab 的 zp2tf 函数的作用是将极点形式的 H(s) 函数的分母展开,本文主要为大家介绍了C++实现Matlab的zp2tf函数示例代码,需要的可以参考一下
    2023-04-04
  • C语言实现超市计价收款系统

    C语言实现超市计价收款系统

    这篇文章主要为大家详细介绍了C语言实现超市计价收款系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C++中Boost的转换函数

    C++中Boost的转换函数

    这篇文章介绍了C++中Boost的转换函数,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • 深入理解c++实现Qt信号和槽机制

    深入理解c++实现Qt信号和槽机制

    信号和槽机制是 Qt 的核心机制,可以让编程人员将互不相关的对象绑定在一起,实现对象之间的通信,本文就来深入理解c++实现Qt信号和槽机制,感兴趣的可以了解一下
    2023-08-08
  • 详解C++中指针和引用的区别

    详解C++中指针和引用的区别

    这篇文章主要介绍了C++中指针和引用的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • 生成随机数rand函数的用法详解

    生成随机数rand函数的用法详解

    本篇文章是对生成随机数rand函数的用法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • FFmpeg中AVIOContext的使用方法详解

    FFmpeg中AVIOContext的使用方法详解

    AVIOContext是FFMPEG管理输入输出数据的结构体,这篇文章主要为大家详细介绍了这个结构体的具体使用,文中的示例代码讲解详细,需要的可以参考一下
    2023-08-08
  • C语言中操作sqlserver数据库案例教程

    C语言中操作sqlserver数据库案例教程

    这篇文章主要介绍了C语言中操作sqlserver数据库案例教程,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++获取指定目录下的所有文件

    C++获取指定目录下的所有文件

    这篇文章主要为大家详细介绍了C++获取指定目录下所有文件的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06

最新评论