C/C++:对象初始化相关
2015-09-28 02:23
579 查看
一、 直接初始化和复制初始化
1.定义:直接初始化使用"( )"符号,如:string s("hello");复制初始化使用"="符号,如:string s="hello".
2.区别:对于内置类型,直接初始化和复制初始化没有差别:其操作都是"提供一个值,并且把这个值复制到新定义的对象中"(《C++ Primer》).
对于类类型,直接初始化根据参数类型调用相应构造函数,复制初始化调用拷贝构造函数,对于以下初始化:
s1的初始化调用String的String(char*)构造函数直接对s1进行初始化,s2的初始化则是先调用String(char*)构造函数构造一临时对象,再调用拷贝构造函数String(const String&)对s2进行初始化.也就是说,如果复制初始化的参数不是同类型的数值,就会多一次临时对象的构造和析构成本.
(如果实验验证,会发现两行代码都调用String(char*)构造函数,这是因为大多数编译器都实行RVO/NRVO((具名)返回值优化)从而避免了临时对象的产生,但了解实际过程,写出不依赖于编译器优化的代码也是必要的)
二、全局/静态变量(对象)的初始化
(参考自:http://bbs.csdn.net/topics/390527051?page=1
http://www.tuicool.com/articles/QRBF3qN)
1.全局变量的初始化分为静态初始化和动态初始化:
静态初始化:编译期进行的初始化,所谓编译期进行的初始化,即在编译期直接将数据放在程序虚拟地址空间的数据段中,因此静态初始化在程序加载到内存时完成.静态初始化又分为 zero-initialization(零初始化)和constant initialization(常量初始化),zero-inltilization指的是对于没有指明初始化式的全局对象,就由编译器用0初始化,并存储在程序的.BSS段 中(由于初始化为0,因此实际上不需要占用空间,在加载到内存时直接初始化为0即可,所以.BSS段的段内容长度为0),const inilitization指的是对于指明常量初始化式的全局对象, 就由指明的初始化式进行初始化.
所有全局对象都会发生静态初始化:指明常量初始化式的进行constant initilization,未指明初始化式的进行zero-initilization,指明非常量初始化式的也会进行zero- initilization(然后在运行期进行动态初始化)
动态初始化:运行时进行的初始化,所谓运行时进行的初始化,不是指在main函数中,事实上,操作系统加载完程序之后,会有默认入口(比如 mainCRTStartup(void) /wmainCRTStartup(void)/WinMainCRTStartup(void)/wWinMainCRTStartup(void)等),visual C++下是 mainCRTStartup(void),mainCRTStartup的任务之一就是进行相关初始化操作,然后调用main函数,因此动态初始化发生在mainCRTStartup执行中,main函数执行前.
指明非常量初始化式的全局对象进行动态初始化,包括需要调用函数的和用其他全局对象初始化的.例如string s,int a=b;
举例:
View Code
由于x只是一个引用,编译器不会调用x的构造函数和析构函数.
至此,这个方案已经比较完美,但它还需要一个成功运行的条件:所有引用x的地方都会include头文件global.h(从而保证s_init_val已定义),"如果某一个全局变量 y 的初始化函数 里没有直接引用 x, 而是间接调用了另一个函数 foo,再通过 foo 引用了 x,此时就可能出错了,因为 y 所在的编译单元里可能并没有直接引用 x,因此很有可能就没有 include 头文 件 global.h,那么 y 的初始化就很有可能发生在 x 之前",在此情况下,此方案没能发挥作用.
"这个问题在 gcc c++ 的标准库里也没有得到解决,有兴趣的可以看看这个讨论".
1.定义:直接初始化使用"( )"符号,如:string s("hello");复制初始化使用"="符号,如:string s="hello".
2.区别:对于内置类型,直接初始化和复制初始化没有差别:其操作都是"提供一个值,并且把这个值复制到新定义的对象中"(《C++ Primer》).
对于类类型,直接初始化根据参数类型调用相应构造函数,复制初始化调用拷贝构造函数,对于以下初始化:
String s1("hello");//String是自定义的字符串类 String s2="hello";
s1的初始化调用String的String(char*)构造函数直接对s1进行初始化,s2的初始化则是先调用String(char*)构造函数构造一临时对象,再调用拷贝构造函数String(const String&)对s2进行初始化.也就是说,如果复制初始化的参数不是同类型的数值,就会多一次临时对象的构造和析构成本.
(如果实验验证,会发现两行代码都调用String(char*)构造函数,这是因为大多数编译器都实行RVO/NRVO((具名)返回值优化)从而避免了临时对象的产生,但了解实际过程,写出不依赖于编译器优化的代码也是必要的)
二、全局/静态变量(对象)的初始化
(参考自:http://bbs.csdn.net/topics/390527051?page=1
http://www.tuicool.com/articles/QRBF3qN)
1.全局变量的初始化分为静态初始化和动态初始化:
静态初始化:编译期进行的初始化,所谓编译期进行的初始化,即在编译期直接将数据放在程序虚拟地址空间的数据段中,因此静态初始化在程序加载到内存时完成.静态初始化又分为 zero-initialization(零初始化)和constant initialization(常量初始化),zero-inltilization指的是对于没有指明初始化式的全局对象,就由编译器用0初始化,并存储在程序的.BSS段 中(由于初始化为0,因此实际上不需要占用空间,在加载到内存时直接初始化为0即可,所以.BSS段的段内容长度为0),const inilitization指的是对于指明常量初始化式的全局对象, 就由指明的初始化式进行初始化.
所有全局对象都会发生静态初始化:指明常量初始化式的进行constant initilization,未指明初始化式的进行zero-initilization,指明非常量初始化式的也会进行zero- initilization(然后在运行期进行动态初始化)
动态初始化:运行时进行的初始化,所谓运行时进行的初始化,不是指在main函数中,事实上,操作系统加载完程序之后,会有默认入口(比如 mainCRTStartup(void) /wmainCRTStartup(void)/WinMainCRTStartup(void)/wWinMainCRTStartup(void)等),visual C++下是 mainCRTStartup(void),mainCRTStartup的任务之一就是进行相关初始化操作,然后调用main函数,因此动态初始化发生在mainCRTStartup执行中,main函数执行前.
指明非常量初始化式的全局对象进行动态初始化,包括需要调用函数的和用其他全局对象初始化的.例如string s,int a=b;
举例:
// global.cpp #include "global.h" // need to ensure memory alignment?? static char g_dummy[sizeof(X)]; static X& x = reinterpret_cast<X&>(g_dummy); int initializer::s_counter_ = 0; void initializer::init() { new(&x) X; } void initializer::clean() { (&x)->~X(); }
View Code
由于x只是一个引用,编译器不会调用x的构造函数和析构函数.
至此,这个方案已经比较完美,但它还需要一个成功运行的条件:所有引用x的地方都会include头文件global.h(从而保证s_init_val已定义),"如果某一个全局变量 y 的初始化函数 里没有直接引用 x, 而是间接调用了另一个函数 foo,再通过 foo 引用了 x,此时就可能出错了,因为 y 所在的编译单元里可能并没有直接引用 x,因此很有可能就没有 include 头文 件 global.h,那么 y 的初始化就很有可能发生在 x 之前",在此情况下,此方案没能发挥作用.
"这个问题在 gcc c++ 的标准库里也没有得到解决,有兴趣的可以看看这个讨论".
相关文章推荐
- [C++ primer]第一章 开始
- c++设计模式-----observer(观察者模式)
- google c++ styles和华为C语言编程规范总结
- c++引用计数的本质
- 获取一个数二进制序列中所有的偶数位和奇数位,分别输出二进制序列。
- C++中重载与重写的理解
- 【C语言】交换两个数组内容(数组一样大)
- Fleury算法求欧拉回路(一)
- emacs怎么编写C语言
- 一些重要的C++ 基础
- 『水一发』『只能算正数的高精度加法』『Cpp』
- C++ 定义和调用函数
- C语言排序实例(选择、冒泡、插入、折半、快速)
- C++ 之内联(inline)函数
- 指向类成员函数的指针
- C++ 之父 Stroustrup 推出“ C++ 核心准则”
- C语言宏定义使用技巧
- 如何学好C语言
- C++ string 类常用函数
- 在C语言中,double、long、unsigned、int、char类型数据所占字节数