构造函数语义学

C++ 构造函数的语义学与实现详解 C++ 构造函数的语义学与实现详解C++ 中构造函数是一种特殊的成员函数,用于在创建对象时进行初始化操作。在 C++ 的类定义中,构造函数是以类名作为函数名来定义的。在上述示例中,我们定义了一个叫做MyClass的类,并定义了三个特殊的成员函数:默认构造函数、带参数的构造函数和析构函数。下面我们分别介绍这三种构造函数的语义学和实现方式。 阅读详情

一  Default constructor的建构操作

nontrivial default constructor的四种情况:

 1. “ 带有 Default Constructor ” 的 Member Class Object

class Foo 
{
    public:
        Foo();
        Foo(int);
}


class Bar
{
    public:
        Foo foo;
        char *str;
}

void foo_bar()
{
    Bar bar;  // bar必须初始化
             // Bar::foo是一个member object,而其class Foo拥有default constructor,符合条件
    if (str)
    ...
}

将 bar::foo 初始化是编译器的事情,但是将Bar::str初始化是程序员的事情,被合成的Bar的default constructor可能是这样的:

inline Bar::Bar()
{
    foo.Foo::Foo();
}

Bar::str并没有被初始化,所以我们需要自己为Bar写一个构造函数。

Bar::Bar()
{
    str = 0;
}

这样写的话 Bar::foo是否被初始化了呢,编译器的行动是:“ 如果编译器 A内含一个或一个以上的member class objects, 那么 class A的每一个构造函数必须调用每一个member classes 的default constructor”,编译器会扩张已有的构造函数,在其中安插一些代码,使得在调用 user code 之前,先调用必要的 member classes 的default constructor 。所以扩张后的代码可能是这样的:

Bar::bar()
{
    foo.Foo::Foo();   // 附加上的compiler code
    str = 0;          // explicit user code 
}

如果有多个 class member objects 都要求constructor 初始化操作,则以 “ member objects在class中的声明次序 ” 来调用各个constructor。

所以有 class member objects 的时候千万别忘了自己定义constructor,给非class member objects(即数据成员)初始化!!!

 

2. “ 带有Default Constructor ” 的 base class 

如果 derived class 没有带有default constructor 派生自 带有 “ default constructor ” 的 base class, 那么这个 derived class 的default constructor 需要被合成出来。 它将调用上一层 base class 的 default constructor。

如果这个 derived class 有多个 constructor ,但是并没有 default constructor,编译器会扩张每一个constructor,将必要调用的 default constructor 加入进去,它不会合成一个新的 default constructor  

 

3. “ 带有一个 Virtual Function ” 的 Class

另有两张情况,需要合成 default constructor :

1. class 声明(或继承)一个 virtual function。

2. class 继承自一个派生链,其中有一个或更多的 virtual base function。

期间编译器会生成 vtbl 和 vptl,vptl 指向 vtbl 。

 

4. “ 带有一个 Virtual Base Class ” 的 Class

必须使 virtual base class 在其每一个 derived class object 中的位置,能够于执行期间准备妥当。

class X 
{
    public:
        int i;
};

class A : public virtual X
{
    public:
        int j;
};

class B : public virtual X
{
    public:
        double d;
};

class C : public A, public B
{
    public:
        int k;
};

// 无法在编译时期决定 pa->X::i 的位置
void foo(const A* pa)
{
    pa->i = 1024;
}

main()
{
    foo(new A);
    foo(new C);
}

编译器无法固定住foo()之中 “ 经由 pa 而存取的 X::i ” 的实际偏移位置,因为 pa 的真正类别可以改变,编译器必须等到执行期才能确定下来。原先的cfront的做法是靠在 derived class object的每一个virtual base class 中安插一个指针完成。所有经由 “ reference ” 或  “ pointer ” 来存取一个 virtual base class 的操作都可以通过相关指针完成。

foo() 可以改下成以下

void foo(const A* pa)
{
    pa->_vbcx->i = 1024;  
}

其中 _vbcx 是编译器产生的指针,指向 virtual base class X。_vbcx 是在 class object 建构期间完成的。对于class所定义的每一个 constructor,编译器会安插那些 “ 允许每一个 virtual base class 的执行期存取操作 ” 的码。如果 class 没有任何 constructor,编译器会为它合成一个 default constructor。

总结 :

 

二  Copy Constructor的建构操作

有三种情况,会以一个 object 的内容作为另一个 class object 的初值。

1. 最明显的一种情况就是对一个 object 做明确的初始化操作:

class X
{
    。。。;
}

X x;
X xx = x;

另两种情况是当 object 被当做参数交给某个函数时,例如:

external void foo(X x);

void bar()
{
    X xx;
    // 以 xx 作为 foo() 第一个参数的初值(不明显的初始化操作)
    foo(xx);
}

以及当函数传回一个 class object 时,例如 :

X foo()
{
    X xx;
    return xx;
}

那么在大部分情况下,当一个 class object 以另一个同类实体作为初值时,上述的 copy constructor 会被调用,这可能会导致一个暂时性 class object 的产生或程序代码的蜕变(或两者都有)。

 

Default Memberwise Initialization   

假如 class 没有提供一个 explicit copy constructor,其内部是以 default memberwise initialization 的手法完成的,也就是每一个内建的或派生的 data member (例如一个指针或者一个数组)的值,从某个 object 拷贝一份到另一个 object 上,不过它并不会拷贝其中的 member class object,而是以递归的形式施行 memberwise initialization。例如:

未完待续...

解释多智能体强化学习(Multi-Agent Reinforcement Learning)(面试题200合集,中频、重要) 多智能体强化学习通过扩展传统强化学习框架,研究多个智能体在动态、交互环境中的策略优化问题。它既有理论上的挑战(如非平稳性和均衡求解),也有广泛的实际应用前景。数学上,它依赖马尔可夫博弈模型,核心是设计算法让智能体在合作或竞争中达到最优。 阅读详情

相关推荐

Windows本地部署Qwen3-14B实战指南:Ollama+Open WebUI零Docker方案

大语言模型本地部署是AI工程化落地的关键环节,其核心在于推理框架兼容性、硬件加速适配性与端到端稳定性。Ollama作为轻量级模型运行时,原生支持Windows DirectML与CUDA,规避了Docker/WSL2虚拟化开销和llama.cpp编译风险;Qwen3-14B则凭借128K上下文、Tool Calling原生支持及中文长文本结构化能力,成为政务、金融等场景首选。本文聚焦Windows平台真实约束——显存阈值、驱动版本匹配、路径编码兼容、离线知识库集成(RAG)等工程细节,提供经63台Windo

weixin_32136203的博客 412

构造函数语意学

本文主要介绍C++有关构造函数的内容。

Spring_24的博客 767

基于51单片机+SYN6288语音播报

51单片机控制SYN6288语音播报资料SYN6288模块原理图语音合成命令接线如何接线实现原理程序代码main.csyn6288.cuart.cdelay.c基于 51单片机的其他项目基于51单片机+遥控灯基于51单片机+LCD1602显示基于51单片机+红外遥控解码+LCD1602显示基于51单片机+DHT11温湿度+LCD1602显示基于51单片机+DS18B20温度测温器+LCD1602显示尾声 资料 我用的是绿深电子技术的模块,资料也挺齐全的。也有相关例程。 SYN6288模块原理图 语音合成

weixin_47457689的博客 3万+

第二章-构造函数语义学

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

冷眼看world的博客 603

AlphaFold-multimer实战:从零开始预测STAT1-STAT2蛋白复合物结构

本文详细介绍了使用AlphaFold-multimer从零开始预测STAT1-STAT2蛋白复合物结构的完整实战流程。内容涵盖环境配置、数据库准备、序列处理、参数优化及结果可信度评估,为研究者利用这一AI工具进行复合物结构预测提供了系统指南和深度解析。

weixin_29094301的博客 885

CNN经典论文(一)LeNet

Gradient-Based Learning Applied to Document Recognition(梯度学习在文档识别中的应用) Yann LeCun, Leon Bottou, Yoshua Bengio, and Patrick Haffner 发表时间:December 1998 期刊:Proceedings of the IEEE 影响:世界上第一个卷积神经网络 论文地址:Gradient-Based Learning Applied to Document Recognition

loveling丶的博客 3597

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

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

803

MTK Tunning ISP 模块面试总结

ISP面试问答

m0_72053187的博客 4537

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

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

290

浅谈天线 - - - GNSS/BT/4G/2.4G

全球定位导航系统,最成熟的就是美利坚,我大中华,俄罗斯,还有就是欧洲的一个(太次不谈)所以我们在项目调试的时候,小尺寸的陶瓷天线上一般兼容2个频段,体积大一点的可以兼容三个频段,采用组合的形式 GPS+BD GPS+GLONASS GLONASS+BD 或者是单频段的定位天线陶瓷PATC陶瓷片:陶瓷片面积越大,介电常数越大,其共振频率越高,接收效果越高,这就是为什么都推荐使用大一点的陶瓷天线的原因银层:陶瓷天线表面的银层可以影响天线的共振频率,理想的GNSS陶瓷片频点准确落在1575.42MH

BLACKHOLE6的博客 1万+

CAPL通过lookupSignal和DBLookup获取DBC信号的属性信息

CAPL通过lookupSignal和DBLookup获取DBC信号的属性信息以及一些相关问题

天赐好车的博客 2884

第2章 构造函数语义学3 : 程序转化语义学

如果 Point3dclass 声明一个或一个以上 virtual functions,或内含一个 virtual base class,那么使用上述函数将会导致那些“被编译器产生的内部 members”的初值被改写。return 指令传回相同类型的局部变量(named value),因此编译器有可能自己做优化,也就是大名鼎鼎的NRVO。但这样不好,会导致出现大量的 constructor ,大大增加了代码维护难度。针对这些程序改写的情况,我们做出一些优化,来避免临时对象的构造拷贝与析构。

qq_40178082的博客 944

测试用例设计工具大盘点:总有一款适合你

本文旨在帮助测试工程师、开发人员及团队管理者快速了解主流测试用例设计工具的特点、适用场景和选择逻辑。覆盖工具类型包括传统文档工具、开源管理工具、商业集成平台及新兴AI工具,范围涵盖中小团队到大型企业的不同需求。本文从“测试用例设计的痛点”切入,用生活案例解释核心概念;接着按“工具类型”分类盘点主流工具(附优缺点对比表);再通过“小团队/中大型团队/敏捷团队”等真实场景教你选工具;最后展望AI等未来趋势,帮你“一次学透,终身受用”。

项目管理的博客 1590

拷贝构造函数语义学

一:拷贝构造函数语义学

qq_38158479的博客 169

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

ssm框架搭建

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

C++对象模型剖析(三)一一构造函数语义学(二)

先看第一个例子public:private:这种时候,就没有必要设置一个 copy cosntructor,这种情况下使用 bitwise copy 既高效又安全。

m0_73170116的博客 1081

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C++对象模型之第二章——构造函数语义学

一、构造函数 编译器会合成4个隐性的非无用的构造函数的情况: 1.含有带有默认构造函数的成员类的对象。 这个合成构造函数只有被真正使用时,才会被合成。这时有一个问题产生,即在多个不同的编译 块产生都各自每个的合成构造函数。如何避免多个默认构造函数产生,将合成的默认、拷贝、析 构、赋值拷贝以inline方式完成。   如果,类成员有多的,编译器不管该类有没有默认构造函数,都会调用每个成

曲终人散 841

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

C++ 构造函数语义学

构造函数是C++中用于初始化对象的特殊成员函数,其语义学涉及编译器的处理方式、对象的构造过程以及与内存管理的交互。

weixin_43050542的博客 570

关于对象及构造函数语义学

1、C++对象模型 如下类在内存中布局如下: class Point { public: Point(float xval); virtual Point(); float x() const; static int PointCount(); protected: virtual ostream&print(ostream& os)const; float

659

第2章 构造函数语义学

2.1 Default Constructor的构建操作 带有“Default Constructor”的Member Class Object 如果一个类没有定义 default construction,就会有一个nontrivial(有用的)constructor被合成,依次调用作为成员的类的default constructor。如果定义了,则扩张该default construct...

nullganbadie的博客 188

构造语义学——默认构造函数与拷贝构造函数

本文所用环境为: 64位机、g++编译器。

qq_46076798的博客 1848

C++对象模型-构造函数语义学 第二章笔记

C++默认构造函数会在需要的时候被产生出来,且只在编译器需要的时候才合成。且合成出来只执行编译器需要的行动。即使合成了默认构造函数,也不会将成员变量初始化为0,若要如此需要程序员提供明显的默认构造函数。 编译器默认构造函数在如下4种情况会合成出来(nontrival default constructor) 成员函数带有默认构造函数,则此class的implicit default constructor就是nontrivial。在构造函数真正需要调用时才会合成默认构造函数 ...

nwao7890的专栏 249

第二章构造函数语义学——关于构造函数和复制构造函数

以下代码体现了书中所说的如下几个知识: 1. 如果一个class没有任何constructor,但它含有一个member object, 而后者有default constructor,编译器需要为该class合成出一个default constructor。(P41) 2. 如果 类中的default constructor已经被显示的定义出来,编译器没办法合成第二个,编译器会采取...

aiyun1242的博客 145

构造函数语义学:默认构造函数合成时机

构造函数语义学:默认构造函数的合成时机

baidu_41922918的博客 444

C++构造函数语义学之默认构造函数

在学C++时,通常有一种概念,在创建类对象时,如果没有构造函数,那么会调用默认的构造函数,并且把相关成员赋值为0,这句话正确吗,看看下面这个例子: #include <iostream> using namespace std; class Foo { public: //Foo() {} void setValue(int value) { m_Value = value; } int m_Value; int *m_pArray; }; i...

琅嬛福地 505

深入探索C++对象模型之构造函数语义学

  C++中编译器背着程序员做了很多事情,导致程序员无法准确的了解到自己所实现的代码本身所具有的性能缺陷。这一章主要谈论C++中构造函数相关的构建行为。 1 默认构造函数的构建行为   一般来说,我们认为在构建一个类时,如果程序员并未给类提供任何相关的构造函数,编译器总是会自动生成默认构造函数,但是实际上的行为却并不完全一致,并且编译器一般不会负责初始化类中的成员对象。但是,在一些情况下,编译器的确会生成相关的默认构造函数来完成一些元素的初始化任务。而具体何时生成一般主要看编译器本身是否需要。言外之意,就是

梦的灰色边沿... 345
上一篇: C++中的 struct 与 class 的区别
下一篇: const_cast / dynamic_cast / static_cast / reinterpret_cast
lfc2017
博客等级 码龄9年 2粉丝 33原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值