当前位置: 首页 > news >正文

Effective C++ iterm4

条款四

--17/01/18

这个条款着重讲的是初始化问题。

(1)构造函数的初始化

最好使用member initialization list进行初始化,这里面存在着效率问题,因为如果在构造函数体内进行初始化的话,那么就会多调用一次default 构造函数,还有内置型对象需要手工初始化,所以一定要使用成员初值列。

(2)不同编译单元的初始化次序问题

不得不说我之前真的没考虑过类似问题,真的是打开了新世界大门啊!

这里主要存在问题的是不同编译单元的non-local static对象,这插播一下:

关于static的用法,C和C++中各有不同的用法,可以参考:

http://blog.csdn.net/majianfei1023/article/details/45290467

关于non-local static对象的说法,可以参考:

http://blog.csdn.net/zhangyifei216/article/details/50549703

里面代码用到了g++编译器进行编译,这里我看不懂,学习了一下:

http://blog.csdn.net/hnyzwtf/article/details/44674145

上面讲得很仔细了,什么是静态局部,什么是静态全局?这里的static对象指的是非堆区和栈区的变量,然后在函数内部定义的是local static对象,除此之外应该都是non-local static对象。不同编译单元指的就是有多个源代码文件,我们可以写个简单代码来验证类似问题(下面代码的编写和编译使用的是linux系统下的vim):

 1 //AB.h
 2 #ifndef AB_H
 3 #define AB_H
 4 #include <iostream>
 5 using namespace std;
 6 
 7 class A {
 8 public:
 9     A() : _val(10) { cout << "A is construct." << endl; }
10     int val() { return _val; }
11 private:
12     int _val;
13 };
14 
15 extern A a;
16 
17 class B {
18 public:
19     B() {
20         cout << "a value is " << a.val() << endl;
21         cout << "B is construct." << endl; 
22     }
23 };
24 #endif
25 
26 //A.cpp
27 #include "AB.h"
28 
29 A a;
30 
31 //B.cpp
32 #include "AB.h"
33 
34 B b;
35 
36 //main.cpp
37 #include <iostream>
38 using namespace std;
39 
40 int main() {
41     cout << "hello world!!" << endl;
42     return 0;
43 }

 

代码中A类似书中的文件系统,有且仅有一个,并且A的构造函数做的就是初始化是将自身的_val变量设为10,并且打印出“A is construct”,然后B要调用A的val()显示_val的值是什么,并且打印出“B is construc”。如果编译器足够聪明,它应该知道我们是要先编译A之后再编译B,不然的话A中的_val就没有被初始化。然而这个编译的顺序在编译器看来时可控,或者说他并没有帮我们设计好编译的顺序,我们打出下面的命令:

g++ A.o B.o main.o -o run1

按照A,B,main的顺序编译,自然输出我们想要的结果:

A is construct.
a value is 10
B is construct.
hello world!!

 

如果是按照B,A,main,也就是下面的命令:

g++ B.o A.o main.o -o run2

结果是:

a value is 0
B is construct.
A is construct.
hello world!!

_val没有被初始化。由此可以得出初始化相对次序并无明确定义。这是个不容忽视的大问题,因为你引用了没有初始化的值会导致一系列问题,因为使用没初始化的变量不是一件好事!

 

书上给出的解决方法是:将每个non-local static对象搬到自己的专属函数内,也就是另外写一个函数,里面放着该对象。这在设计模式里面称作singleton模式。下面给出需要改进的地方:

 1 //A.cpp
 2 #include "AB.h"
 3 
 4 A& a() {
 5     static A _a;
 6     return _a;
 7 }
 8 
 9 //AB.h
10 class B {
11 public:
12     B() {
13         cout << "a value is " << a().val() << endl;
14         cout << "B is construct." << endl; 
15     }
16 };

 

 

按照g++ B.o A.o main.o -o run2编译之后运行得到如下结果:

A is construct.
a value is 10
B is construct.
hello world!!

 

单例模式果然强大!!可行的原因如下:当你要用A对象的时候,你就调用a(),这时候如果_a没有初始化的话就初始化,已经初始化的话那么就直接返回_a,这就达到了我们全程只有一份A对象的目的了。

转载于:https://www.cnblogs.com/scoyer/p/6306114.html

相关文章:

  • 用虚拟 router 连通 subnet - 每天5分钟玩转 OpenStack(141)
  • ECMAScript 6 入门
  • 指令周期 机器周期 状态周期 振荡时钟周期(时钟周期)(转)
  • 关于java的print()
  • Laravel / Lumen 实践总结
  • 对象存储、快存储、文件存储的区别
  • 恶意程序入侵 dbuspm-session 发现了新的方法制这种恶意程序
  • 图示 Smart-Art
  • js中的正则表达式入门
  • Maven中的SNAPSHOT版本和正式版本理解
  • rabbitMq ubuntu下安装
  • 搜索框自动联想功能
  • JavaWeb应用出现HTTP 500-Unable to compile class for JSP 错误 的解决
  • Go 语言入门一: Go 安装
  • Go 获取当前可执行文件的所在目录
  • 2017 前端面试准备 - 收藏集 - 掘金
  • CAP理论的例子讲解
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • SegmentFault 2015 Top Rank
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • supervisor 永不挂掉的进程 安装以及使用
  • swift基础之_对象 实例方法 对象方法。
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 深度学习在携程攻略社区的应用
  • 突破自己的技术思维
  • 我有几个粽子,和一个故事
  • 译米田引理
  • Java数据解析之JSON
  • k8s使用glusterfs实现动态持久化存储
  • python最赚钱的4个方向,你最心动的是哪个?
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • ​VRRP 虚拟路由冗余协议(华为)
  • #传输# #传输数据判断#
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (day6) 319. 灯泡开关
  • (转)Mysql的优化设置
  • .NET Core跨平台微服务学习资源
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .net 设置默认首页
  • .NET 中 GetHashCode 的哈希值有多大概率会相同(哈希碰撞)
  • .NetCore 如何动态路由
  • .Net开发笔记(二十)创建一个需要授权的第三方组件
  • .net中生成excel后调整宽度
  • @Bean注解详解
  • @Documented注解的作用
  • [《百万宝贝》观后]To be or not to be?
  • [Android Studio 权威教程]断点调试和高级调试
  • [C++][基础]1_变量、常量和基本类型
  • [C语言]——柔性数组
  • [EFI]英特尔 冥王峡谷 NUC8i7HVK 电脑 Hackintosh 黑苹果efi引导文件
  • [Java][Android][Process] ProcessBuilder与Runtime差别