题目如下:问下列代码的打印结果为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;

}

打印结果是不定的,不一定为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); 

可见没有分配新的内存。



正确的方式:

struct CLS

{

    int m_i;

    CLS( int i ) : m_i(i){}

    CLS()

    {

        new (this)CLS(0);

    }

};

另: 若构造函数调用自身,则会出现无限递归调用,是不允许的

tricky c++ new(this)的更多相关文章

  1. Codefoces 429 D. Tricky Function

    裸的近期点对.... D. Tricky Function time limit per test 2 seconds memory limit per test 256 megabytes inpu ...

  2. Codeforces Round #245 (Div. 1) 429D - Tricky Function 最近点对

    D. Tricky Function Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 codeforces.com/problemset/problem/42 ...

  3. Educational Codeforces Round 1 A. Tricky Sum 暴力

    A. Tricky Sum Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/598/problem ...

  4. 算法训练 Tricky and Clever Password

     算法训练 Tricky and Clever Password   时间限制:2.0s   内存限制:256.0MB      问题描述 在年轻的时候,我们故事中的英雄——国王 Copa——他的私人 ...

  5. Codeforces 196 E. Tricky and Cleve Password

    \(>Codeforces \space 196\ E. Tricky\ and\ Cleve\ Password<\) 题目大意 : 给出一个有 \(n\) 个结点,\(m\) 条边的连 ...

  6. Codeforces 30 E. Tricky and Cleve Password

    \(>Codeforces \space 30\ E. Tricky\ and\ Cleve\ Password<\) 题目大意 : 给出一个串 \(S\),让你找出 \(A, B, C\ ...

  7. CodeForces - 598A Tricky Sum (数学,快速幂的运用)

    传送门: http://codeforces.com/problemset/problem/598/A A. Tricky Sum time limit per test 1 second memor ...

  8. Codeforces Round #456 (Div. 2) A. Tricky Alchemy

    传送门:http://codeforces.com/contest/912/problem/A A. Tricky Alchemy time limit per test1 second memory ...

  9. Codeforces 429D Tricky Function(平面最近点对)

    题目链接  Tricky Function $f(i, j) = (i - j)^{2} + (s[i] - s[j])^{2}$ 把$(i, s[i])$塞到平面直角坐标系里,于是转化成了平面最近点 ...

  10. Codeforces(429D - Tricky Function)近期点对问题

    D. Tricky Function time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

随机推荐

  1. 大数据-HDFS 集群搭建的配置文件

    1.HDFS简单版集群搭建相关配置文件 1.core-site.xml文件 <property> <name>fs.defaultFS</name> <val ...

  2. 【C++】递归 课后习题3-13、3-14

    // // main.cpp // 3-13递归Fibonacci级数 // // Created by T.P on 2018/3/21. // Copyright © 2018年 T.P. All ...

  3. 浅谈Linux下/etc/passwd文件

    浅谈Linux 下/etc/passwd文件 看过了很多渗透测试的文章,发现在很多文章中都会有/etc/passwd这个文件,那么,这个文件中到底有些什么内容呢?下面我们来详细的介绍一下. 在Linu ...

  4. sql计算上一周(解决了跨年会出错的问题)

    1.问题描述: 使用YEARWEEK('时间字段')=YEARWEEK(NOW())-1来筛选上一周数据时,当遇到跨年的时候会出现计算错误的问题. eg: 如上图,当前日期为2020年1月6日.上图标 ...

  5. Bandicam(班迪录屏)高清视频录制工具

    Bandicam(班迪录屏)简单好用的录屏幕,录游戏,录视频的功能强大的屏幕录像软件,比起其他软件其性能更加卓越. 与其他软件相比,用Bandicam录制的视频大小更小, 不仅保证原文件的质量.

  6. 17.python自定义模块的导入方式

    1.直接用import导入 最后运行main.py可以看到命令行窗口输出了一句:你好,这样就完成了. 2.通过sys模块导入自定义模块的路径path 3.在环境变量中找到自定义模块 这个方法原理就是利 ...

  7. 深入理解协程(二):yield from实现异步协程

    原创不易,转载请联系作者 深入理解协程分为三部分进行讲解: 协程的引入 yield from实现异步协程 async/await实现异步协程 本篇为深入理解协程系列文章的第二篇. yield from ...

  8. vue中动态设置echarts画布大小

    document.getElementById('news-shopPagechart').style.height = this.heightpx2+'px'; //heightpx2定义在data ...

  9. [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause报错问题的解决

    run SQL: select version(),@@sql_mode;SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY','' ...

  10. python——pickle模块的详解

    pickle模块详解 该pickle模块实现了用于序列化和反序列化Python对象结构的二进制协议. “Pickling”是将Python对象层次结构转换为字节流的过程, “unpickling”是反 ...