23_神秘的临时对象

0. 问题:下面的程序输出什么?为什么?

#include <stdio.h>

class Test
{
private:
    int mi;
public:
    Test(int i)
    {
        mi = i;
    }

    Test()
    {
        Test(0);
    }

    void print()
    {
        printf("mi = %d\n", mi);
    }

};

int main()
{

    Test t;

    t.print();

    return 0;
}

输出结果:

mi = -1216962560
  • 程序意图:在Test()中以0作为参数调用Test(int i), 将成员变量mi的初始值值为0。
  • 运行结果:成员变量mi的值为随机值

为什么会这样???

1. 思考:构造函数是一个特殊函数,因此:

  • 是否可以直接调用? ——可以(构造函数可以自动调用和手动调用)
  • 是否可以在构造函数中调用构造函数?——(编译器编译可以通过)
  • 直接调用构造函数的行为是什么?后果是什么?

答案:

  • 直接调用构造函数将产生一个临时对象
  • 临时对象的生命周期只有一条语句的时间,过了这一条语句的时间,临时对象自动被析构函数析构而不复存在
  • 临时对象的作用域只在一条语句中
  • 临时对象是C++中值得警惕的灰色地带

编程说明:去掉临时变量

#include <stdio.h>

class Test
{
private:
    int mi;
    
    void init(int i)    // 添加init(int i)初始设置函数
    {
        mi = i;
    }
public:
    Test(int i)
    {
        init(i);
    }

    Test()
    {
        init(0);    
    }

    void print()
    {
        printf("mi = %d\n", mi);
    }

};

int main()
{

    Test t;

    t.print();

    return 0;
}

输出结果:

mi = 0

2. 编译器的行为

现代C++编译器在不影响最终执行结果的前提下,会尽力减少临时对象的产生!!!

3. 小结

  • 直接调用构造函数将会产生一个临时对象
  • 临时对象是性能的瓶颈,也是bug的来源之一
  • 现代C++编译器会尽力避开临时对象
  • 实际工程开发中需要人为的避开临时对象,因此,在写代码和在设计上要有意识的避开临时对象
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容