C++简明分析临时对象是什么

 更新时间:2022年04月23日 10:57:02   作者:清风自在 流水潺潺  
对性能来说,许多的问题都需要和出现频率及本身执行一次的开销挂钩,有些问题虽然看似比较开销较大,但是很少会执行到,那也不会对程序有大的影响;同样一个很小开销的函数执行很频繁,同样会对程序的执行效率有很大影响。本章中作者主要根据临时对象来阐述这样一个观点

一、初探临时对象

1.问题

下面的程序输出什么?为什么?

下面编写程序进行实验:

#include <stdio.h>
class Test {
    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

运行结果:

  • 成员变量 mi 的值为随机值

2.思考

构造函数是一个特殊的函数

  • 是否可以直接调用?
  • 是否可以在构造函数中调用构造函数?
  • 直接调用构造函数的行为是什么?

3.答案

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

可以将上面代码写成这样,避免临时对象:

#include <stdio.h>
class Test {
    int mi;
    void 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;
}

输出结果如下:

再来看一个程序,深刻体会一下临时对象:

#include <stdio.h>
class Test {
    int mi;
    void init(int i)
    {
        mi = i;
    }
public:
    Test(int i) {
        printf("Test(int i)\n");
        init(i);
    }
    Test() {
        printf("Test()\n");
        init(0);
    }
    void print() {
        printf("mi = %d\n", mi);
    }
    ~Test()
    {
        printf("~Test()\n");
    }
};
int main()
{
    printf("main begin\n");
    Test();
    Test(10);
    printf("main end\n");
    return 0;
}

输出结果如下:

这个程序很好的说明了临时对象的生命周期只有一条语句的时间(过了这条 C++ 语句,临时对象将被析构而不复存在)

二、编译器的行为

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

下面来看一个例子:

#include <stdio.h>
class Test
{
    int mi;
public:
    Test(int i)
    {
        printf("Test(int i) : %d\n", i);
        mi = i;
    }
    Test(const Test& t)
    {
        printf("Test(const Test& t) : %d\n", t.mi);
        mi = t.mi;
    }
    Test()
    {
        printf("Test()\n");
        mi = 0;
    }
    int print()
    {
        printf("mi = %d\n", mi);
    }
    ~Test()
    {
        printf("~Test()\n");
    }
};
Test func()
{
    return Test(20);
}
int main()
{
    //Test t(10); 等价于 Test t = Test(10);
    Test t = Test(10); // ==> Test t = 10;
    Test tt = func();  // ==> Test tt = Test(20); ==> Test tt = 20;
    t.print();
    tt.print();
    return 0;
}

输出结果如下:

注意两点:

  • 通过输出结果可以看到【编译器并没有按照生成临时对象,再用临时对象初始化 t 对象(其中涉及调用拷贝构造函数)】的步骤,因为现代的编译器都会尽力避免临时对象的产生。
  • Test t = Test(10); 等价于 Test t = 10; 写成Test t = 10; 可以杜绝临时对象的产生。因为临时对象的产生会带来性能上的问题,Test t = Test(10); 相当于调用了两次构造函数, 而 Test t = 10; 少调用一次函数,性能得到提升。

三、小结

  • 直接调用构造函数将产生一个临时对象
  • 临时对象是性能的瓶颈,也是 bug 的来源之一
  • 现代 C++ 编译器会尽力避开临时对象
  • 实际工程开发中需要人为的避开临时对象

到此这篇关于C++简明分析临时对象是什么的文章就介绍到这了,更多相关C++临时对象内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 二叉树先根(先序)遍历的改进

    二叉树先根(先序)遍历的改进

    这篇文章主要介绍了二叉树先根(先序)遍历的改进,有需要的朋友可以参考一下
    2014-01-01
  • c++如何实现Base64算法

    c++如何实现Base64算法

    这篇文章主要介绍了c++如何实现Base64算法,文中讲解非常细致,帮助大家更好的理解和学习c++,感兴趣的朋友可以了解下
    2020-08-08
  • FFmpeg中AVIOContext的使用方法详解

    FFmpeg中AVIOContext的使用方法详解

    AVIOContext是FFMPEG管理输入输出数据的结构体,这篇文章主要为大家详细介绍了这个结构体的具体使用,文中的示例代码讲解详细,需要的可以参考一下
    2023-08-08
  • C++中sprintf()函数的使用详解

    C++中sprintf()函数的使用详解

    本篇文章是对C++中sprintf()函数的使用进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C++中的extern声明变量详解

    C++中的extern声明变量详解

    这篇文章主要介绍了C++中的extern声明变量详解,本文讲解了声明和定义、extern声明全局变量、extern声明函数等内容,需要的朋友可以参考下
    2015-03-03
  • C++报错:Segmentation Fault的解决方案

    C++报错:Segmentation Fault的解决方案

    段错误(Segmentation Fault)是 C++ 编程中常见且令人头疼的错误之一,段错误通常发生在程序试图访问未被允许的内存区域时,导致程序崩溃,本文将深入探讨段错误的产生原因、检测方法及其预防和解决方案,需要的朋友可以参考下
    2024-07-07
  • C语言中的分支循环其嵌套语句

    C语言中的分支循环其嵌套语句

    这篇文章主要介绍了C语言中的分支循环其嵌套语句,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • C++中类的成员函数及内联函数使用及说明

    C++中类的成员函数及内联函数使用及说明

    这篇文章主要介绍了C++中类的成员函数及内联函数使用及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • C++适用于所有输入法的解决方案

    C++适用于所有输入法的解决方案

    这篇文章主要介绍了C++适用于所有输入法的解决方案,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2025-02-02
  • C语言在头文件中定义const变量详解

    C语言在头文件中定义const变量详解

    这篇文章主要介绍了C语言在头文件中定义const变量详解的相关资料,需要的朋友可以参考下
    2017-05-05

最新评论