温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

神秘的临时对象(十八)

发布时间:2020-06-16 03:08:56 来源:网络 阅读:658 作者:上帝之子521 栏目:编程语言

        我们在程序中不可避免的会遇到临时变量,那么在 C++ 中也会不可避免的会遇到临时对象。我们以代码为例来进行分析

#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;
}

        我们这段代码是想要在 Test() 中以 0 作为参数调用 Test(int i),然后将成员变量 mi 初始化为 0,最后想要打印它的值。我们来看看编译结果

神秘的临时对象(十八)

        我们看到打印的是一个随机数,并不是我们所期望的 0。那这到底是怎么回事呢?那么我们想下:构造函数既然是一个特殊的函数。那么它是否可以直接调用呢?是否可以在构造函数中调用构造函数呢?直接调用构造函数的行为是什么?我们就直接说答案了。直接调用构造函数将产生一个临时对象,临时对象的生命周期只有一条语句的时间,临时对象的作用域只在一条语句中,临时对象是 C++ 中值得警惕的灰色地带!上面那个程序也就是说第 15 行的调用的构造函数会产生临时对象,它的生命周期只有那一行的时间,所以在后面我们打印出来的才会是一个随机值。

        下面我们在上面程序的基础上进行修改,代码如下

#include <stdio.h>

class Test
{
private:
    int mi;
    
    void init(int i)
    {
        mi = i;
    }
public:
    Test()
    {
        init(0);
    }
    
    void print()
    {
        printf("mi = %d\n", mi);
    }
};

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

        我们再次编译看看结果

神秘的临时对象(十八)

        这次我们看到它按照我们所想要的初始化为 0 了。现代的 C++ 编译器在不影响最终执行结果的前提下,会尽力减少临时对象的产生!!!

        我们再来看一个示例代码

#include <stdio.h>

class Test
{
private:
    int mi;
public:
    Test(int i)
    {
        mi = i;
        printf("Test(int i): %d\n", mi);
    }
    Test(const Test& obj)
    {
        mi = obj.mi;
        printf("Test(const Test& obj): %d\n", mi);
    }
    Test()
    {
        mi = 0;
        printf("Test()\n");
    }
    void print()
    {
        printf("mi = %d\n", mi);
    }
    ~Test()
    {
        printf("~Test()\n");
    }
};

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

int main()
{
    Test t = Test(10);
    Test tt = func();
    
    t.print();
    tt.print();
    
    return 0;
}

        我们看到在第 40 行定义了 Test 对象 t,并将它初始化为 10。按照我们想的它在这块先是生成一个临时对象初始化为 10 并将这个临时对象赋值给对象 t。所以这块可能会牵扯到拷贝构造函数。第 41 行也是这样的,先是在 func 函数中生成一个临时对象 Test(50),并将它赋值给对象 tt。所以也会牵扯到拷贝构造函数。那么我们来编译下看看结果

神秘的临时对象(十八)

        我们看到并没有打印出拷贝构造函数的身影。再回想下我们之前讲的,现代编译器已经大大优化了,尽量会避免临时对象的产生。那么第 40 行将会等价于 Test t(10),第 41 行将会等价于 Test tt = Test(50) ==> Test tt(50);所以这样也就能解释清楚了,它确实没牵扯到拷贝构造函数。我们得随时注意 C++ 中的临时对象,因为它将会导致一些莫名其妙的结果。通过对临时对象的学习,总结如下:1、直接调用构造函数将产生一个临时对象,临时对象是性能的瓶颈,也是 bug 的来源之一;2、现代 C++ 编译器会尽力避开临时对象,实际工程开发中需要人为的避开临时对象。


        欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI