tricky c++ new(this)
2024-10-08 07:55:46
题目如下:问下列代码的打印结果为0吗?
#include <stdlib.h>
#include <iostream>
using namespace std;
struct CLS
{
int m_i;
CLS( int i ) : m_i(i){}
CLS()
{
CLS(0);
}
};
int main()
{
CLS obj;
cout << obj.m_i << endl;
system("PAUSE");
return 0;
}
#include <iostream>
using namespace std;
struct CLS
{
int m_i;
CLS( int i ) : m_i(i){}
CLS()
{
CLS(0);
}
};
int main()
{
CLS obj;
cout << obj.m_i << endl;
system("PAUSE");
return 0;
}
打印结果是不定的,不一定为0
代码奇怪的地方在于构造函数中调用了自己的另一个构造函数
我们知道,当定义一个对象时,会按顺序做2件事情:
1)分配好内存(非静态数据成员是未初始化的)
2)调用构造函数(构造函数的本意就是初始化非静态数据成员)
显然上面代码中,CLS obj;这里已经为obj分配了内存,然后调用默认构造函数,但是默认构造函数还未执行完,却调用了另一个构造函数,这样相当于产生了一个匿名的临时CLS对象,它调用CLS(int)构造函数,将这个匿名临时对象自己的数据成员m_i初始化为0;但是obj的数据成员并没有得到初始化。于是obj的m_i是未初始化的,因此其值也是不确定的
从这里,我们归纳如下:
1)在c++里,由于构造函数允许有默认参数,使得这种构造函数调用构造函数来重用代码的需求大为减少
2)如果仅仅为了一个构造函数重用另一个构造函数的代码,那么完全可以把构造函数中的公共部分抽取出来定义一个成员函数(推荐为private),然后在每个需要这个代码的构造函数中调用该函数即可
3)偶尔我们还是希望在类的构造函数里调用另一个构造函数,可以按下面方式做:
在构造函数里调用另一个构造函数的关键是让第二个构造函数在第一次分配好的内存上执行,而不是分配新的内存,这个可以用标准库的placement new做到:
先看看标准库中placement new的定义
inline void *__cdecl operator new(size_t, void *_P)
{
return (_P);
}
{
return (_P);
}
可见没有分配新的内存。
正确的方式:
struct CLS
{
int m_i;
CLS( int i ) : m_i(i){}
CLS()
{
new (this)CLS(0);
}
};
{
int m_i;
CLS( int i ) : m_i(i){}
CLS()
{
new (this)CLS(0);
}
};
另: 若构造函数调用自身,则会出现无限递归调用,是不允许的
最新文章
- W5200移植W5500驱动教程
- HTML5之废弃和更新的元素与属性
- ORACLE SQL调优案例一则
- java保留两位小数
- web前端基础篇②
- CSS预处理器实践之Sass、Less大比拼[转]
- regexp_substr在oracle9i的替换方案
- 【OpenCV新手教程之十二】OpenCV边缘检測:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑
- POJ 1142 质因数分解
- hdu1013
- JTextArea与TextArea自动换行和滚动条的区别对比
- Java核心技术 卷I chapter05 继承
- 4.写一个控制台应用程序,接收一个长度大于3的字符串,完成下列功能: 1)输出字符串的长度。 2)输出字符串中第一个出现字母a的位置。 3)在字符串的第3个字符后面插入子串“hello”,输出新字符串。 4)将字符串“hello”替换为“me”,输出新字符串。 5)以字符“m”为分隔符,将字符串分离,并输出分离后的字符串。 */
- Script error.解决方法
- DAY16 模块和包的导入
- IDEA 在某个工程下一个module如何使用另一个module中的资源文件(.xml .prop等)
- 架设SVN服务器
- 前端学习 -- 内联框架iframe
- 去掉if
- 关于ng-if的理论性知识你了解多少?
热门文章
- react 报红错误汇总
- 如何解决Selenium句柄、多窗口问题
- Python PyInstaller安装和使用教程
- .NET Core将促使.NET进一步衰落
- spring-boot序章:打造博客系统
- License for package Android SDK Build-Tools 28.0.3 not accepted
- python 多进程处理图像,充分利用CPU
- 【Spring Boot 源码解读】之 【为何引入了 Jedis 依赖最后用的还是 Lettuce 客户端?】
- SQL 配置管理器无法连接到WMI
- SpringCloud之Feign(五)