题目如下:问下列代码的打印结果为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. 从零开始安装Redis 集群(Linux CenOS7)

    从零开始安装Redis 集群(Linux CenOS7) 使用ISO安装CentOS7虚拟机 配置静态IP(参考Mac VMware Fusion CentOS7配置静态IP) 安装vim [root ...

  2. JAVA并发之锁获取步骤及锁优化

    在另外的两篇文章中先后介绍了轻量级同步关键字volatile和重量级锁关键字synchronized,这两个关键字是Java语言中进行线程同步的基本方式(当然还有ReentrenLock等显式锁方式) ...

  3. Sql Server执行一条Update语句很慢,插入数据失败

    今天同事要我修改服务器数据库里面的2条数据,查看服务器上的SQL Server数据库的时候,发现这几天数据没有添加成功,然后发现磁盘很快就满了,执行Update语句时,执行半天都提示还在执行,查询语句 ...

  4. 【GeneXus】开发移动APP时,如何使用Canvas进行布局?

    当我们开发移动端APP的时候,经常遇到一种布局方式,那就是层级的布局,比如:一张照片我想在照片的上面显示它的名称,但不影响我照片展示的布局大小,也就是这个名称是浮在照片上的,如图: 如果要实现这样的布 ...

  5. selenium中的xpath用法,使用xpath定位元素

    xpath路径选择器定位元素 1. xpath: 使用路径表达式来定位xml或者html中文档中选取节点.在 XPath 中,有七种类型的节点:元素.属性.文本.命名空间.处理指令.注释以及文档节点( ...

  6. python的break、continue、pass

    break break可以用来立即退出循环语句(包括else)continue continue可以用来跳过当次循环注意:break和continue都是只对离他最近的循环起作用 pass pass是 ...

  7. Logback源码分析

    在日常开发中经常通过打印日志记录程序执行的步骤或者排查问题,如下代码类似很多,但是,它是如何执行的呢? package chapters; import org.slf4j.Logger; impor ...

  8. numpy 索引和切片

    一.取行 1.单行 数组[index, :] # 取第index+1行 例子 import numpy as np arr1 = np.arange(0, 24).reshape(4, 6) # 取第 ...

  9. synchronized底层实现

    1.锁升级的过程 当多个线程同时竞争一个对象监视器时:当前对象结构中的mark word中是否是当前线程id,如果是则当前线程获得偏向锁. 如果不是,则通过CAS将当前线程id置换到mark word ...

  10. 【JDK1.8】 Java小白的源码学习系列:HashMap

    目录 Java小白的源码学习系列:HashMap 官方文档解读 基本数据结构 基本源码解读 基本成员变量 构造器 巧妙的tableSizeFor put方法 巧妙的hash方法 JDK1.8的putV ...