C++对象模型 学习笔记②

构造函数语义学

默认构造函数

两大误解

  1. 任何class 如果没有定义default constructor,就会被合成一个出来。
  2. 编译器合成出来的default constructor 会明确设定“class 内每一个data member 的默认值”

  上述两个最常见的看法,都是错误的。
  默认构造函数实际上是被编译器需要的,用以实现一些多态机制,而非对类成员进行初始化(程序员的职责)。

四种会合成默认构造函数的情况:

  • 类的某一个成员带有默认构造函数
      此时需要通过编译器构造的默认构造函数调用成员的默认构造函数。
  • 类的父类带有默认构造函数
      此时需要通过编译器构造的默认构造函数调用父类的默认构造函数。
  • (父类或自身)带有虚函数的类
      此时需要通过编译器构造的默认构造函数构造虚函数表和虚函数表的指针(实现多态)。
  • 带有虚基类的类
      此时需要通过编译器构造的默认构造函数构造虚基类指针,其用于在执行期进行存取操作。
      注意:若程序员已经定义了默认构造函数(编译器无法再生成一个),编译器会在已有的默认构造函数前添加一些代码实现其需要的功能(上述提到的四个)。
      其他没有构造函数的类实际上不会合成默认构造函数!!!
    存在默认构造函数的类定义会被转换如下:
X xx;

//转换如下
	//定义(占用内存的行为)
X xx;
	//初始化
xx.X::X();

默认拷贝构造函数

三种可能调用拷贝构造函数的情况:

  • 对一个对象做明确的初始化操作。
class X{};
X x;
X xx = x;//以一个对象的值初始化另一个对象的值
  • 作为参数交给某个函数时
extern void foo(X x);
void bar()
{
	X xx;
	foo(xx);//作为参数传递
}
  • 函数返回值(NRV优化可能就不会再调用拷贝构造函数了)
X foo_bar()
{
	X xx;
	return xx;//作为返回值
}

  和默认构造函数一样,默认拷贝构造函数实际上是为编译器服务的(实现安全的多态),除了处理实现编译器功能的一些内置数据外(例如虚表指针,虚基类表等)对于数据成员,其直接进行Bitwise Copy Semantic(位逐次拷贝),即不会处理深浅拷贝之类的问题(应该由程序员进行处理)。

四种会合成默认拷贝构造函数的情况:

  • 类的某一个成员带有拷贝构造函数
      此时需要通过编译器构造的默认拷贝构造函数调用成员的拷贝构造函数。
  • 类的父类带有拷贝构造函数
      此时需要通过编译器构造的默认拷贝构造函数调用父类的拷贝构造函数。
  • 带有虚函数的类
      此时需要通过编译器构造的默认拷贝构造函数构造虚函数表(割裂时实现正确多态)。
  • 带有虚基类的类
      此时需要通过编译器构造的默认拷贝构造函数构造虚基类指针,其用于在执行期进行存取操作。

程序转化语意学

上一小节提到了三种调用拷贝构造函数的地方,其中第三种在NRV优化下将调用构造函数而非拷贝构造函数

  1. 明确的初始化
X x0;

X x1(x0)
X x2 = x0;
X x3 = X(x0);

//转换为下
	//定义被重写,初始化操作被剥除
X x1;
X x2;
X x3;
	//编译器安插拷贝构造函数
x1.X::X(x0);
x2.X::X(x0);
x3.X::X(x0);
  1. 参数的初始化
void foo(X x0);

X xx;
foo(xx);

//转换为下
	//改变函数声明
void foo(X& x0);
	//改变调用方式
X xx;
X __temp0;
__temp0.X::X(xx);
foo(__temp0);
  1. 返回值的初始化——若NRV优化,不再使用拷贝构造函数
X bar()
{
	X xx;

	return xx;
}

//NRV优化前
void bar(X& __result)
{
	X xx;
	xx.X::X();

	__result.X::X(xx);
	return;
}
//NRV优化后
void bar(X& __result)
{
	__result.X::X();
	
	return;
}

  NRV(Named Return Value)优化是编译器在函数返回某个在其内部定义的变量时所做的优化(内部变量的类型和返回类型相同),已经较为普遍的存在。

成员们的初始化列表

四种必须使用初始化列表的情况:

  1. 初始化一个reference member。
  2. 初始化一个const member。
  3. 调用一个base class 的constructor且它拥有一组参数。
  4. 调用一个member class的constructor且它拥有一组参数。

注意编译器对初始化列表一一处理但可能会改变顺序!!!
  例如:编译器按照成员的声明顺序进行初始化而非在初始化列表中的顺序。不过,可以保证的是初始化列表在用户的函数代码之前运行。并且由于this指针已经存在了,所以在初始化列表或者构造函数体内可以使用成员函数(注意相关数据顺序逻辑,容易出现问题日)。

总结

  这是我自己整理的学习笔记,主要用于自我复习。如果有大佬也看到了这个并且发现了谬误,欢迎email me at lonelytaoist@qq.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一些可以作为C++对象模型学习的优秀免费资源: 1. C++ Primer Plus(第六版):虽然这本书不是免费的,但你可以在一些在线图书馆或网站上找到电子版的免费样章,以及作者提供的一些免费资源,包括练习题和代码示例。 2. C++ Reference(cppreference.com):这是一个广泛的C++在线参考资料,提供了对C++语言特性、标准库和对象模型的详细解释和示例代码。它是一个非常好的资源,无论是初学者还是有经验的开发者都可以从中受益。 3. C++ Object Model and Memory Management by Stanford University(斯坦福大学):这是斯坦福大学的一门在线课程,涵盖了C++对象模型和内存管理的基础知识。课程提供了视频讲座、幻灯片和练习题,可以帮助你深入理解C++对象模型的概念和原则。 4. C++ Object Model and Memory Management by University of Illinois(伊利诺伊大学):这是伊利诺伊大学的一门在线课程,专注于C++对象模型和内存管理。课程提供了讲座视频、幻灯片和编程作业,可以帮助你加深对C++对象模型的理解,并提高你的编程技巧。 5. C++ Object Model Explained by Eli Bendersky:这是一篇由Eli Bendersky撰写的文章,详细解释了C++对象模型的工作原理和实现细节。文章包含了大量的图表和示例代码,非常适合希望深入了解C++对象模型的开发者阅读。 这些资源提供了广泛而丰富的信息,可以帮助你学习和理解C++对象模型的概念和原则。记住,在学习过程中,实践是非常重要的,尝试编写一些涉及对象模型的代码,以加深你对该主题的理解和熟悉度。祝你在学习C++对象模型时取得成功!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值