欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

Cpp 对象模型探索 / 成员初始化列表

发布时间:2024/10/14 编程问答 61 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Cpp 对象模型探索 / 成员初始化列表 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

目录

一、何时必须使用?

二、优势

三、细节探究


一、何时必须使用?

  • 成员变量是 const 类型。 
  • 成员变量是引用。
  • 基类中含有带形参的构造函数且不存在默认的构造函数。
  • 成员变量是类对象,该对象含有带形参的构造函数且不存在默认的构造函数。
  • 二、优势

    #include <iostream>class X {X(int value = 0) :m_i(value){printf("this = %p", this);std::cout << "X(int)构造函数被调用" << std::endl;}X(const X &tmpv){printf("this = %p", this);std::cout << "X 拷贝构造函数被调用" << std::endl;}X& operator=(const X &tmp){printf("this = %p", this);std::cout << "X 赋值运算符被调用" << std::endl;return *this;}~X(){printf("this = %p", this);std::cout << "X 析构函数被调用" << std::endl;}public:int m_i; };class A { public:X xobj; A(){ xobj = 1000; } };int main() {A aobj;return 0; }

    结果

    this = 00CFFA60X(int)构造函数被调用 this = 00CFF89CX(int)构造函数被调用 this = 00CFFA60X 赋值运算符被调用 this = 00CFF89CX 析构函数被调用 this = 00CFFA60X 析构函数被调用

    从编译器角度分析上述结果的原由,如下:

     

    class A { public:X xobj; A()// 从编译器角度分析,在初始化列表中,执行了如下代码。// X xobj; 此处仅仅是执行了申请 sizeof(X) 大小的内存块。// xobj.X::X(); 在上述内存块中执行构造函数。{ // 从编译器角度分析,此处的代码如下:// X xtmp; 此处仅仅是执行了申请 sizeof(X) 大小的内存块。// xtmp.X::X(); 在上述内存块中执行构造函数。// xobj.operator=(xtmp); 此处执行赋值构造函数。xobj = 1000; } };

    若将代码 xobj = 1000; 移入构造函数初始化列表中,则结果如下:

    this = 00AFF82CX(int)构造函数被调用 this = 00AFF82CX 析构函数被调用

    省略了创建临时变量和赋值的操作,即:在成员初始化列表中初始化变量,优势是提高程序运行效率。 

    三、细节探究

  • 成员初始化列表中的代码可以看成编译器插入到构造函数体最前面的代码,即:最先被执行。
  • 成员初始化列表中变量初始化顺序是变量在类中的定义顺序,而不是在初始化列表中排布的顺序。
  • 栗子:

    #include <iostream> class A { public:A():k_(100),i_(k_){std::cout << "i_ = " << i_ << std::endl;std::cout << "k_ = " << k_ << std::endl;} private:int i_;int k_; };int main() {A aobj;return 0; }

    结果

    i_ = -858993460 k_ = 100

     由此可知,上述的结论是正确的。

     

    (SAW:Game Over!)

    总结

    以上是生活随笔为你收集整理的Cpp 对象模型探索 / 成员初始化列表的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。