C++对象模型(16)-- 构造函数语义学:临时对象

C++拷贝构造函数—类临时对象的构建与析构 临时对象一般是调用拷贝构造函数来创建的,分为以下两种情况: ①对象作为实参初始化形参时(值传递) ②对象作为函数返回值(值传递) 阅读详情

临时对象是栈上的没有名字的对象,它在源码中是不可见的,是编译器偷偷摸摸在背后干的。

比如下面的代码就会产生临时对象:

int i = 1;

// 这里的 i++ 会产生临时对象,这里的临时对象是在系统中产生,代码中看不见的
// 首先将i的值赋给临时对象,再把临时对象的值作为返回结果赋给j,再对i进行自增操作。
int j = i++;

临时对象有以下几个特点:

(1)临时对象是在栈上生成的。

(2)临时对象是右值,可通过“const 左值引用”绑定临时对象,或通过右值绑定临时对象。

(3)临时对象的产生和销毁会调用1次构造函数和析构函数。

临时对象的产生和销毁需要消耗系统资源,所以在写代码时应尽量避免临时对象的产生。

1、临时对象的产生及解决办法

临时对象主要产生在下列场景中:

(1)在栈中生成无名对象时

Integer objI = Integer(1);

先产生一个Integer临时对象,然后调用拷贝构造函数生成objI对象。

解决办法:在定义时直接初始化。

Integer objI(1);
Integer objI{1};

(2)类型转换

class MyDemo {
public:
    MyDemo(){}

    MyDemo(int i) {
        std::cout << "构造函数MyDemo(int i)" << std::endl;
    }

    MyDemo& operator = (const MyDemo& _demo) {
        std::cout << "赋值运算符" << std::endl;
        
        return *this;
    }

    ~MyDemo() {
        std::cout << "析构函数" << std::endl;
    }
};

int main()
{

    MyDemo demo;
    demo = 100;

    return 0;
}

这里的demo = 100,会产生临时对象:

(1)将 100为参数调用了MyDemo的构造函数创建了一个临时对象;

(2)通过拷贝赋值运算符,将临时对象的成员值赋给了demo;

(3)销毁临时对象。

解决办法:创建对象时进行初始化。

MyDemo demo = 100;

(3)隐式类型转换

void testFunc(const MyDemo& demo) {}

int main()
{
    int i = 2;
    testFunc(i);
    
    return 0;
}

上面的testFunc(i),会产生临时对象。int值会先转换成MyDemo类型的临时对象,然后赋值给形参demo。

解决办法:

将传入的实参和函数的形参类型保持一致即可:

testFunc(MyDemo(i));

(4)函数参数

函数的参数传值是值传递,在函数调用时系统会创建一个临时对象。

class MyDemo {
public:
    MyDemo() {}

    MyDemo(int i) {
        std::cout << " 构造函数MyDemo(int i)" << std::endl;
    }

    MyDemo(const MyDemo& _demo) {
        std::cout << " 拷贝构造函数" << std::endl;
    }

    ~MyDemo() {
        std::cout << " 析构函数" << std::endl;
    }
};

void testFunc(MyDemo demo) {
    std::cout << " testFunc" << std::endl;
}

int main()
{
    MyDemo demo;
    testFunc(demo);
    
    return 0;
}

从执行结果可以看到,在调用testFunc()函数时,指向了拷贝构造函数。

解决办法:把值传递改成引用传递。

void testFunc(MyDemo& demo) {}

(5)函数返回值

在函数返回对象时候,会创建一个临时对象接收这个对象;从而调用了拷贝构造函数,和析构函数。

MyDemo testFunc() {
    MyDemo demo;

    return demo;
}

int main()
{
    MyDemo demo = testFunc();

    return 0;
}

解决办法:

(1)修改testFunc的形参,把返回对象作为形参传入函数。

MyDemo testFunc(MyDemo& ret) {}

(2)用右值接收返回值

MyDemo&& d = testFunc();

C++编译器会对没有构造函数的类生成默认构造函数吗? 之前在上C++的课的时候,印象中有那么一句话: 如果一个类没有任何构造函数,那么编译器会生成一个默认的构造函数 今天在看《深度探索C++对象模型》的第二章:“构造函数语意学”的时候发现之前听到的说法是错误的。 比如说如下代码: class A { public: int a; }; int main(void) { A a; a.a = 4; A a2; ... 阅读详情

相关推荐

算法-基于MACD的Adaboost股价涨跌预测模型

MACD是一个指标,具体用法是MACD>0看涨,反之看跌,果真是这样的吗?由于所有的技术指标都基于对历史数据的统计,指标的滞后性也就难免,有时候MACD明明大于0,股价仍然跌,有时候macd小于0,股价仍然涨。 本文基于Adaboost算法提出了一种基于macd的线性阀值分类器作为若分类器,通过在限定的解空间内寻找使得错误率最小的阀值和偏置,这样做避免了训练若分类器的复杂性,经验证,这种方法有效。

mtaxot的博客 8023

c++临时对象

我们知道在C++的创建对象是一个费时,费空间的一个操作。有些固然是必不可少,但还有一些对象却在我们不知道的情况下被创建了。通常以下三种情况会产生临时对象:  1,以值的方式给函数传参;  2,类型转换;  3,函数需要返回一个对象时; 现在我们依次看这三种情况:   一,以值的方式给函数传参。   我们知道给函数传参有两种方式。1,按值传递;2,按引用传递。按值

信手涂鸦 1666

别只当玩具!聊聊这个555金属探测器电路背后的电磁感应与RLC调谐原理

本文深入解析了555金属探测器电路的工作原理,重点探讨了电磁感应与RLC调谐原理。通过分析电感线圈的电磁特性、RLC谐振电路的行为以及555定时器的多重功能,揭示了这一看似简单的装置如何实现金属检测。文章还提供了灵敏度优化方案和常见问题解决方法,帮助读者从科学角度理解这一实用技术。

weixin_29204205的博客 478

第二章-构造函数语义学

这节打破两个C++新手观点: 任何类如果没有定义默认构造函数就会被合成一个出来 合成出来的默认构造函数会设定类内每个数据成员的初始值 默认构造函数的建构操作 默认构造函数在被需要的时候才被编译器产生出来 class Foo {...} void foo_bar() { Foo bar; if (bar.val || bar.pnext) ... } 这里需要Foo有个默认构造函数能将val和pnext初始化为0,可惜的是这里并不满足上面所说的“被需要的时候”,因为被需要是被编译器需要,这里只是

冷眼看world的博客 603

MATLAB基础应用精讲-【数模应用】PPO算法(附python代码实现)(二)

表示为状态转移概率和动作选择概率的乘积,因为状态和动作决定轨迹。

qq_36130719的博客 413

区块链技术与应用 【全国职业院校技能大赛国赛题目解析】Caliper从0到使用

技能大赛样题解析,caliper题目从0到使用

weixin_52865146的博客 2080

C++ 临时对象的生成与构造函数

在学习到C++ peimer plus第十章构造函数小节时,对于临时对象的生成出现一些疑问,现在暂时记录出现的问题,能以后深入学习了看是否能够解决。第二种语法:允许调用构造函数创建一个临时的对象,通过临时对象来把内容复制到stock2中。像这种在赋值语句中使用构造函数给已经存在的对象赋值的时候会创建临时对象。第一种语法:这种情况与第一种方式一模一样,不会创建临时的对象。对于这种隐式的调用构造函数的情况不会生成临时对象。第一种:按值传递参数会生成临时对象。第三种:函数返回一个对象的时候。

weixin_60735782的博客 280

STMicroelectronics 系列:STM32G4 系列_(11).STM32G4系列编程基础

通过本文,我们学习了如何在 STM32CubeIDE 中搭建开发环境,创建新项目,配置 GPIO、定时器和 ADC 外设,并编写相应的代码示例。这些基础知识将帮助你快速上手 STM32G4 系列的编程。希望本文对你有所帮助,祝你编程愉快!

2401_87715305的博客 1279

C++对象模型(15)-- 构造函数语义学:移动构造函数和移动赋值运算符

移动构造函数、移动赋值运算符没有内存的搬迁或者内存拷贝,所以可以提高效率。

803

【unity游戏开发入门到精通——UGUI】UI控件 —— Image图像控件

【unity游戏开发入门到精通——UGUI】UI控件 —— Image图像控件

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 2357

QT+Halcon实现螺纹检测

工业上要检测螺丝的内外直径、内外牙距、内外角度,现在比较好用的图像处理库,开源的opencv,收费的有halcon。为了实现螺纹检测,和对比螺纹检测拿个库比较好。分别用opencv和halcon实现了螺纹检测,通过对比发现用halcon实现的效果比较。现在用博客把实现过程记录下来: 1、需要检测的螺纹数据如下: 2、为了实现检测螺丝以上数据,螺纹内径、螺纹外径、螺纹外牙距、螺纹...

专注现代C++实战,从核心语法到高性能编程,助力开发者深入掌握系统级编程精髓。 7052

深度探索C++对象模型之美

从概念来上来讲,每一个没有定义构造函数的类都会由编译器来合成一个默认构造函数,以使得可以定义一个该类的对象,但是默认构造函数是否真的会被合成,将视是否有需要而定。C++ standard 将合成的默认构造函数分为 trivial(不重要) 和 notrivial(重要) 两种,前文所述的四种情况对应于notrivial默认构造函数,其它情况都属于trivial。对于一个trivial默认构造函数,编译器的态度是,既然它全无用处,干脆就不合成它。

谢谢大家的关注 3494

LVGL core theme主题管理(lv_theme.c)

如果打开宏,主题的初始化是在显示设备注册时完成的。整个themes的实现放在目录下面。这里一共有三套主题(basic、default和mono)可供选择或者参考。源码中默认对接的是 default 主题,所以在中,看到的是调用default主题的接口。也就是说,如果需要更换主题,把这里面的接口换掉就可以了。或者要重新做一套主题,参考这些实现修改也就可以了。虽说有三套主题,但逻辑流程是一样的。主要完成两个工作:构造lv_theme_t结构体和初始化默认样多备用(style_init函数内实现)。构造。....

Bigan(安)的博客 3413

深度解读《深度探索C++对象模型》之C++的临时对象(一)

所谓临时对象就是当编译器需要一个空间来暂存表达式的求值结果时临时创建的一个未命名的对象。编译器根据程序的需要可能会安插一些临时变量来支持程序的运行,这些动作是在程序员不可感知的背后默默进行,所以我们有必要了解编译器在背后的所作所为。这些动作有时是为了转换原来的代码的语义以保证代码能顺利地编译通过,有的是为了程序运行的正确性而暂存的对象。

iShare_Carlos的博客 1454

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

深度解读《深度探索C++对象模型》之C++的临时对象(二)

这一篇来讲解临时对象的生命周期,上篇讲解何时产生临时对象,这篇讲解临时对象存在的时间以及何时会被销毁。

iShare_Carlos的博客 1372

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

c++临时对象详解

1,临时对象神秘在于不知不觉就请入程序当中,并且给程序带来了一定的问题; 2,下面的程序输出什么?为什么? 1 #include <stdio.h> 2 3 class Test 4 { 5 int mi; 6 public: 7 Test(int i) 8 { 9 mi = i; 10 } 11 12 Test() // 这里程序作者想要代码复用,直接调用已经构造好的函数来完成没有参数的构造函数的函数体;

程序猿的博客 1650

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

C++对象模型_第四章_C++数据语义学

下面的方式打印成员变量指针。// 16printf("pmyobj->m_n偏移值 = %d\n", mypoint);由于类内存模型会遵循字节对齐,以4字节对齐为例,如果一个变量不满足4字节,编译器会对这个内存进行填充到4字节。下面代码,将小内存的变量char 如果连续定义完后,再定义int,总内存8字节;如果int在char中间定义,总内存12字节。int m_i1;char m_c2;char m_c3;

weixin_43916755的博客 977

c++ 对象模型

title: object-mode-layout date: 2022/09/12 tags: c++对象模型 categories: c++对象模型

勤天下而拥家 1357

深入理解C++对象模型

1. C++对象模型 所有的非静态数据成员存储在对象本身中。所有的静态数据成员、成员函数(包括静态与非静态)都置于对象之外。另外,用一张虚函数表(virtual table)存储所有指向虚函数的指针,并在表头附加上一个该类的type_info对象,在对象中则保存一个指向虚函数表的指针。如下图: image17_thumb1.png 一个类的对象的内存大小包括: 所有非静态数据成员的大小。 由内存对齐而填补的内存大小。 为了支持virtual有内部产生的额外负担。 如下类: ..

Mr_YZL_1992的博客 1485

深入分析C++对象模型之C++移动构造函数

C++11新标准中最重要的特性之一就是引入了支持对象移动的能力,移动语义的加持使得移动一个如容器之类的大对象的成本可以像复制一个指针一样低廉了,于是出现了各种各样的传言:如编译器会使用移动操作来替代拷贝操作以获得效率上的提升,甚至说将符合C++98标准的以前的老代码用符合C++11新标准的编译器重新编译一次,一行代码未改即可获得运行速度上质的提升。对于种种传闻,事实上是否如此?

iShare_Carlos的博客 1231

C++临时对象生命周期

可以思考一下上面的代码能否通过编译?如果可以会输出什么?

qq_45523675的博客 1397

深度解读《深度探索C++对象模型》之C++默认构造函数

C++的默认构造函数的作用是什么?什么时候会需要一个默认构造函数,以及默认构造函数从哪里来?这篇文章将从编译器的角度来分析这个问题。

iShare_Carlos的博客 1378

深度解读《深度探索C++对象模型》之C++拷贝构造函数(二)

C++的拷贝构造函数什么时候会被生成出来?它完成了哪些功能?本篇将从编译器的角度出发,结合编译器生成的汇编代码,深入分析什么情况下编译器会生成一个拷贝构造函数,以及拷贝构造函数里面做了什么事情。

iShare_Carlos的博客 1273

C++对象模型实践探索

C++对象模型是个常见、且复杂的话题,本文基于Itanium C++ ABI通过程序实践介绍了几种 简单C++继承 场景下对象模型,尤其是存在虚函数的场景,并通过图的方式直观表达内存布局。本文展示的程序构建环境为Ubuntu,glibc 2.24,gcc 6.3.0。由于clang和gcc编译器都是基于Itanium C++ ABI,因此本文介绍的对象模型对clang编译的程序也基本适用。含有虚函数的类,编译器会为其添加一个虚函数表(vptr。

kfashfasf的博客 1209

CPP之对象模型

一、C++对象模型在c++中,class data members有两种:static、nonstatic;class member function有三种:static 、nonstatic、virtual;例如:下面这个class Pointclass Point { public: Point(float xval); virtual ~Point(); float x() con...

qq_32164245的博客 595

C++临时对象

要理解临时对象,可能先需要搞清楚lvalue,rvalue的区别: 每个表达式的结果都是lvalue或rvalue。lvalue指的是内存中持续存储数据的一个地址。而rvalue是临时存储的表达式结果。之所以称为lvalue,是因为所有产生lvalue的表达式都可以出现在赋值语句中等号的左边,如果表达式结果不是lvalue,则他是rvalue。(引用自深入理解visual c++入门经典Page...

勤学如春起之苗,不见其增,日有所长! 辍学如磨刀之石,不见其损,日有所亏! 187
上一篇: C++对象模型(15)-- 构造函数语义学:移动构造函数和移动赋值运算符
下一篇: C++对象模型(17)-- 构造函数语义学:成员初始化列表
老蔡编程
博客等级 码龄23年 48粉丝 75原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值