第23课.神秘的临时对象

Posted huangdengtao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第23课.神秘的临时对象相关的知识,希望对你有一定的参考价值。

1.下面程序输出什么?为什么?

#include <stdio.h>

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

    Test()
    {
        Test(0);       //直接调用了构造函数,会产生一个临时对象;Test(0)这个构造函数对这个临时对象进行初始化后。就被析构函数销毁了。所以对这个程序而言。这句话没有任何意义。才导致了,打印的随机值。
    }
    
    void print()
    {
        printf("mi = %d
", mi);
    }
};

int main()
{
    Test t;
    
    t.print();
    
    return 0;
}

技术图片

思考:

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

答案:

a.直接调用构造函数将会产生一个临时对象;
b.临时对象的生命周期只有一条语句的时间
c.临时对象的作用域只在一条语句中

eg:

#include <stdio.h>

class Test
{
    int mi;
    
    void init(int i)        //在实际工程中往往会提供一个私有的init函数来做初始设置
    {
        mi = i;
    }
    
public:
    Test(int i)
    {
        printf("Test(int i)
");
        init(i);            //调用init初始函数
    }

    Test()
    {
        printf("Test()
");
        init(0);            //调用init初始函数
    }
    
    void print()
    {
        printf("mi = %d
", mi);
    }
    
    ~Test()
    {
        printf("~Test()
");
    }
};

int main()
{
    printf("main begin
");
    
    /*    通过这段代码更加的说明了上述答案中所述的三项   
     */
    Test();        //Test().print; 
    Test(0);       //Test(0).print;
    
    printf("main end
");
    
    return 0;
}

技术图片

2.编译器的行为

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

#include <stdio.h>

class Test
{
    int mi;

public:
    Test(int i)
    {
        printf("Test(int i) : %d
", i);
        mi = i;
    }
   
    Test(const Test& t)
    {
        printf("Test(const Test& t) : %d
", t.mi);
        mi = t.mi;
    }
    
    Test()
    {
        printf("Test()
");
        mi = 0;
    }
    int print()
    {
        printf("mi = %d
", mi);
    }
    ~Test()
    {
        printf("~Test()
");
    }
};

Test func()
{
    return Test(20);
}

int main()
{
    Test t(10);             //Test t(10);  等价于 Test t = Test(10);            
                            //理论上 1.生成临时对象; 2.用临时对象初始化t对象; 3.调用拷贝函数
                            //实际上Test t = Test(10); ==》(编译器把这里优化为) Test t = 10; 不会产生临时对象
                            //实际工程中推荐使用Test t = 10这种写法,不推荐使用Test t(10)

    Test tt = func();       //Test tt = func(); ==》Test t = Test(20);==》Test t = 20; 不会缠身临时对象
    
    t.print();
    tt.print();
                       
    return 0;
}

技术图片

Test t[] = {Test(), Test(10), Test[10]};        //与上述类似

3.总结

直接的,简单的调用构造函数会生成临时对象;

Test(10); 

间接的调用构造函数则会被编译器优化,不会生成临时函数;

Test t = Test(10);

Test t[] = {Test(), Test(10), Test[20]}; 

以上是关于第23课.神秘的临时对象的主要内容,如果未能解决你的问题,请参考以下文章

学习linux第一堂课 设置临时IP

神秘的临时对象(十八)

带有神秘附加字符的 Javascript Date getTime() 代码片段

第13课 右值引用

第14课 右值引用_基本概念

第03课:Spring Boot 启动原理