NR.5: Don't use two-phase initialization

NR.5:不要使用两阶段初始化

Reason(原因)

Splitting initialization into two leads to weaker invariants, more complicated code (having to deal with semi-constructed objects), and errors (when we didn't deal correctly with semi-constructed objects consistently).

将初始化分为两部分会导致不变性较弱,代码更复杂(必须处理半结构化对象)和错误(当我们不能始终如一地正确处理半结构化对象时)。

Example, bad(反面示例)

// Old conventional style: many problems

class Picture{    int mx;    int my;    char * data;public:    // main problem: constructor does not fully construct    Picture(int x, int y)    {        mx = x;         // also bad: assignment in constructor body                        // rather than in member initializer        my = y;        data = nullptr; // also bad: constant initialization in constructor                        // rather than in member initializer    }

    ~Picture()    {        Cleanup();    }

    // ...

    // bad: two-phase initialization    bool Init()    {        // invariant checks        if (mx <= 0 || my <= 0) {            return false;        }        if (data) {            return false;        }        data = (char*) malloc(mx*my*sizeof(int));   // also bad: owning raw * and malloc        return data != nullptr;    }

    // also bad: no reason to make cleanup a separate function    void Cleanup()    {        if (data) free(data);        data = nullptr;    }};

Picture picture(100, 0); // not ready-to-use picture here// this will fail..if (!picture.Init()) {    puts("Error, invalid picture");}// now have a invalid picture object instance.
Example, good(范例)
class Picture{    int mx;    int my;    vector data;    static int check_size(int size)    {        // invariant check        Expects(size > 0);        return size;    }public:    // even better would be a class for a 2D Size as one single parameter    Picture(int x, int y)        : mx(check_size(x))        , my(check_size(y))        // now we know x and y have a valid size        , data(mx * my * sizeof(int)) // will throw std::bad_alloc on error    {        // picture is ready-to-use    }    // compiler generated dtor does the job. (also see C.21)    // ...};Picture picture1(100, 100);// picture is ready-to-use here...// not a valid size for y,// default contract violation behavior will call std::terminate thenPicture picture2(100, 0);// not reach here...
Alternative(代替选项)
  • Always establish a class invariant in a constructor.

    始终在构造函数中建立类不变式。

  • Don't define an object before it is needed.

    不要在需要之前定义对象。

原文链接

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#nr5-dont-use-two-phase-initialization

新书介绍

《实战Python设计模式》是作者最近出版的新书,拜托多多关注!

本书利用Python 的标准GUI 工具包tkinter,通过可执行的示例对23 个设计模式逐个进行说明。这样一方面可以使读者了解真实的软件开发工作中每个设计模式的运用场景和想要解决的问题;另一方面通过对这些问题的解决过程进行说明,让读者明白在编写代码时如何判断使用设计模式的利弊,并合理运用设计模式。

对设计模式感兴趣而且希望随学随用的读者通过本书可以快速跨越从理解到运用的门槛;希望学习Python GUI 编程的读者可以将本书中的示例作为设计和开发的参考;使用Python 语言进行图像分析、数据处理工作的读者可以直接以本书中的示例为基础,迅速构建自己的系统架构。


觉得本文有帮助?请分享给更多人。

关注微信公众号【面向对象思考】轻松学习每一天!

面向对象开发,面向对象思考!

malloc 初始化_C++核心准则NR.5:不要使用两阶段初始化相关推荐

  1. modbus软件开发实战指南_C++核心准则?GSL:指南支持库

    GSL: Guidelines support library GSL:指南支持库 The GSL is a small library of facilities designed to suppo ...

  2. 初始化一个java空数组_Java 数组的两种初始化方式

    一.数组 1.数组中存储元素的类型是统一的,每一个元素在内存中所占用的空间大小是相同的,知道数组的首元素的内存地址,要查找的元素只要知道下标,就可以快速的计算出偏移量,通过首元素内存地址加上偏移量,就 ...

  3. blob转file对象_C++核心准则C.41:构造函数生成的对象应该被完全初始化

    C.41: A constructor should create a fully initialized object C.41构造函数生成的对象应该被完全初始化 Reason(原因) A cons ...

  4. java 成员变量声明顺序_C++核心准则讨论:按照成员声明的顺序定义和初始化成员变量...

    Discussion: Define and initialize member variables in the order of member declaration 讨论:按照成员声明的顺序定义 ...

  5. C++核心准则​NR.3:不要拒绝使用异常

    NR.3: Don't avoid exceptions NR.3:不要拒绝使用异常 Reason(原因) There seem to be four main reasons given for n ...

  6. C++核心准则​NR.4:不要坚持将每个类声明放在其自己的源文件中

    NR.4: Don't insist on placing each class declaration in its own source file NR.4:不要坚持将每个类声明放在其自己的源文件 ...

  7. 判断exception类型_C++核心准则T.44:使用函数模板推断类模板参数类型(如果可能)...

    T.44: Use function templates to deduce class template argument types (where feasible) T.44:使用函数模板推断类 ...

  8. 无符号数的减法_C++核心准则ES.107:不要使用无符号数下标,使用gsl::index更好

    ES.107: Don't use unsigned for subscripts, prefer gsl::index ES.107:不要使用无符号数下标,使用gsl::index更好 Reason ...

  9. c++ file* 句柄泄漏_C++核心准则?讨论:持有没有被句柄管理的资源时切勿抛出异常...

    Discussion: Never throw while holding a resource not owned by a handle 讨论:持有没有被句柄管理的资源时切勿抛出异常 Reason ...

  10. c 函数多次声明_C++核心准则C.132:不要没有理由就将函数声明为虚函数

    岫玉 C.132: Don't make a function virtual without reason C.132:不要没有理由就将函数声明为虚函数 Reason(原因) Redundant v ...

最新文章

  1. 【文本分类】Attention Is All You Need
  2. Navicat 2003-can't connect to MYSQL server on 'localhost'(10061)
  3. 独家 | 用pandas-profiling做出更好的探索性数据分析(附代码)
  4. 大话设计模式之装饰模式
  5. SpringSecurity-短信验证码接口开发
  6. matlab 的excel 对象,MATLAB 中的 COM 对象
  7. jaas_受JAAS保护的JAX-RS端点
  8. python 函数内部声明全局变量
  9. linux 压缩和解压缩命令
  10. java 多队列_java多线程实现简单队列
  11. boost知识点查阅
  12. onchange 与 onblur
  13. 【原】基于matlab的蓝色车牌定位与识别---绪论
  14. 页面动态加载android,Android APP启动页面动态加载全部权限
  15. ubuntu14.04 安装 pyv8
  16. 永续公债(or统一公债)的麦考利久期(Macaulay Duration)的计算
  17. 使用yigo遇到的小问题
  18. 头哥实践教学平台 CC++程序设计(计算机程序设计)基本输入输出
  19. excel从右边查找字符并截取
  20. solr mysql 导入命令_Solr 07 - Solr从MySQL数据库中导入数据 (Solr DIH的使用示例)

热门文章

  1. Linux平台搭建Discuz
  2. javascript 浮点计算问题解决思路
  3. 教你编写高性能的mysql语法
  4. 静态页面对seo优化之详解
  5. 理解 Delphi 的类(十) - 深入方法[8] - 如果忘了返回值
  6. 微信小程序canvas 图片绘制
  7. Spring Cloud(Greenwich版)-02-服务注册与服务发现-Eureka入门
  8. 微信取消分享后还是执行成功函数
  9. Kibana将语言设置为中文
  10. python微软产品一般都一个25位的序列号_Python易错点6