C++ 初始化随机数发生器器问题

关于C/C++中全局变量的初始化问题的深入思考 - 推酷
关于C/C++中全局变量的初始化问题的深入思考
前日,在一次C++课程上,刘老师在举例说明构造函数和析构函数的功能时,提到了全局变量初始化时的构造函数的行为。构造函数在main函数之前初始化全局变量。当然在C++下我是深信不疑的。但随后老师声称C语言下的全局变量也是如此,因为C没有构造和析构函数,所以我们无法看到这一过程,在C++下可以在构造和析构函数中向屏幕打印信息,进而可以观察全局变量的初始化和生存期。
这个观点无疑使我心头一震,作为C的痴迷者,长期以来在我头脑中的印象是,全局变量在编译期就完成初始化了。难道我的观念是错误的?!难道C真的也是在main函数之前,在程序运行初期才初始化?!
于是我翻看了《C语言参考手册》这本书上没有明确的答案,再翻看著名的K&R的《C程序设计语言》中只有括号里面的一句话“在概念上.......”也是含糊其辞。(现在想想这个问题可能和编译器有关,所以丹爷爷也没说明太多)
在网上查询了一下,关于这个问题,持什么观点的都有,没有一个权威的答案。
只能靠自己了,动手实验!
先给出我的结论
C和C++中的一般全局变量(不包括类class)是在编译期确定的初始值,而不是在程序运行时,在main函数之前初始化的。
C++中的类的全局变量是在程序运行时,在main函数之前初始化的。
预热知识:
C或者C++语言,明面上的入口函数是main(argc,argv),或者tmain、wmain、WinMain等等。但实际上,是C Runtime的startup代码中的
void&mainCRTStartup(void)函数
,调用了编程者写的main函数。这个函数定义在VisualC++安装目录的crt\src\目录下的某个.c文件中(视VC++的版本不同,存放的文件也不同)。它在执行一些初始化操作,如获取命令行参数、获取环境变量值、初始化全局变量、初始化io的所需各项准备之后,调用main(argc,argv)。main函数返回后,mainCRTStartup还需要调用全局变量的析构函数或者atexit()所登记的一些函数。往深里说,是在链接生成可执行文件时,告诉链接器这个可执行文件的entry就是mainCRTStartup。当然,我们也可以对编译器进行设置,使其不插入mainCRTStartup函数代码
以VC++6.0为例设置:Project-&Settings-&Link 在Category中选择Output,在Entry-point symbol中填上main 即可。
-------------------------
1,&&&&&C语言环境下:
实验准备:
int main(void)
return a+3 ;
在编译器中设置入口函数为main(具体方法见上面)
这样,我们让编译器生成的程序,直接从main函数中进入,而不是先执行mainCRTStartup函数做一些准备工作。
结果预测:
这样,如果函数返回的是3,则说明此全局变量是在编译期就被初始化为0了,如果函数返回的是其它数字,则说明此全局变量是在程序运行时,main函数运行前进行的初始化。
实验结果:
进入控制台(运行cmd命令),运行编译后的程序(因为程序没有向屏幕输出结果,我们看不到任何现象),继续输入命令:echo& %ERRORLEVEL% 则显示3,此即为函数的返回值。
(echo是显示其后的值,系统把前面运行的程序的返回值放在%ERRORLEVEL%中,故我们可以通过此方法获得主函数的返回值)
同理:对于结构体全局变量
int main(void)
return sTest.a+3 ;
函数也返回3.
实验结论:
在C语言中,全局变量是在编译期完成初始化的。
(在本实验中我们没有使用I/O函数把结果打印出来,因为I/O函数的调用之前必须要初始化内存中的某堆空间,而这个工作是由main函数之前的mainCRTStartup函数来做的。而我们设置让编译器跳过这个函数,故会在运行时出错。)
C++语言环境下
实验准备:
A(){a=10;}
int main(void)
return cTest.
结果预测:
这样,如果函数返回的是0,则说明此全局变量是在编译期就被初始化为0了,如果函数返回的是其它数字,则说明此全局变量是在程序运行时,main函数运行前进行的初始化。
实验结果:
在编译器中设置入口函数为main,主函数返回一个其他值
在编译器中设置入口函数为默认,主函数返回值为10
实验结论:
在C++中,类(class)的全局变量是在程序运行期,main函数开始之前,调用类的构造函数完成初始化的。
把C中的代码放到C++下实验
int main(void)
return a+3 ;
结果与C的结果相同。
在C++中一般全局变量的初始化(类除外),是在编译期完成的,而不是在运行期完成。(与C语言规则相同)
mainCRTStartup函数不管一般全局变量的初始化,它管理类(class)的全局变量的初始化,调用类的析构函数。
编译器会在编译时,初始化一般全局变量为0.
具有全局生命期的局部静态变量的初始化,与局部变量相同都是在运行时,执行到该初始化语句完成初始化的,只是局部静态变量只初始化一次。
1、程序不是从主函数开始执行的,而是先要执行一些启动代码。(现在明白为什么要在在嵌入式软件编程时要在工程中添加类似于75x_init.s和75x_vect.s这两个汇编文件了吧)
2、你应该给主函数以返回值。实际上标准C只规定了两种形式的main函数:
int main( void ) 和 int main(int argc, char *argv[])
main返回0,告诉系统程序正常终止,返回非零值告诉系统程序异常关闭.
我们可以利用程序的返回值,控制要不要执行下一个程序。
例:程序名&&DOS命令
前面的程序正常执行后才执行后面的DOS命令。当然我们也可以用其它的逻辑符把程序和命令组织起来,来实现复杂的功能。
(UNIX中的shell命令也有类似功能)
已发表评论数()
&&登&&&陆&&
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见|||||| 更多
比特客户端
我们也在这里:
关于初始化C++类成员的问题
关键字:C++
  在使用C++编程的过程当中,常常需要对类成员进行初始化,通常的方法有以下两种:
  第一种方法
  CMYClass::CSomeClass()
  第二种方法
  CMYClass::CSomeClass() : x(0), y(1){}
  本文将要探讨这两种方法的异同以及如何使用这两种方法。
  从技术上说,第二种方法比较好,但是在大多数情况下,两者实际上没有什么区别。第二种语法被称为成员初始化列表,之所以要使用这种语法有两个原因:一个原因是必须这么做,另一个原因是出于效率考虑。 让我们先看一下第一个原因--必要性。设想你有一个类成员,它本身是一个类或者结构,而且只有一个带一个参数的构造函数。
  class CMember {
  public:
  CMember(int x) { … }
  因为CMember有一个显式声明的构造函数,编译器不产生一个缺省构造函数(不带参数),所以没有一个整数就无法创建CMember的一个实例。
  CMember* pm = new CM // 出错!!
  CMember* pm = new CMember(2); // OK
  如果CMember是另一个类的成员,你怎样初始化它呢?答案是你必须使用成员初始化列表。
  class CMyClass {
  CMember m_
  public:
  CMyClass();
  // 必须使用初始化列表来初始化成员 m_member
  CMyClass::CMyClass() : m_member(2)
  没有其它办法将参数传递给m_member,如果成员是一个常量对象或者引用也是一样。根据C++的规则,常量对象和引用不能被赋值,它们只能被初始化。
  使用初始化列表的第二个原因是出于效率考虑,当成员类具有一个缺省的构造函数和一个赋值操作符时。MFC的CString提供了一个完例子。假定你有一个类CMyClass具有一个CString类型的成员m_str,你想把它初始化为"Hi,how are you.".你有两种选择:
  CMyClass::CMyClass() {
  // 使用赋值操作符
  // CString::operator=(LPCTSTR);
  m_str = _T("Hi,how are you.");
  // 使用初始化列表
  // 和构造函数 CString::CString(LPCTSTR)
  CMyClass::CMyClass() : m_str(_T("Hi,how are you."))
  在它们之间有什么不同吗?是的。编译器总是确保所有成员对象在构造函数体执行之前被初始化,因此在第一个例子中编译的代码将调用CString::Cstring来初始化m_str,这在控制到达赋值语句前完成。在第二个例子中编译器产生一个对CString:: CString(LPCTSTR)的调用并将"Hi,how are you."传递给这个函数。结果是在第一个例子中调用了两个CString函数(构造函数和赋值操作符),而在第二个例子中只调用了一个函数。
  在CString的例子里这是无所谓的,因为缺省构造函数是内联的,CString只是在需要时为字符串分配内存(即,当你实际赋值时)。但是,一般而言,重复的函数调用是浪费资源的,尤其是当构造函数和赋值操作符分配内存的时候。在一些大的类里面,你可能拥有一个构造函数和一个赋值操作符都要调用同一个负责分配大量内存空间的Init函数。在这种情况下,你必须使用初始化列表,以避免不要的分配两次内存。
  在内建类型如ints或者longs或者其它没有构造函数的类型下,在初始化列表和在构造函数体内赋值这两种方法没有性能上的差别。不管用那一种方法,都只会有一次赋值发生。有些程序员说你应该总是用初始化列表以保持良好习惯,但我从没有发现根据需要在这两种方法之间转换有什么困难。在编程风格上,我倾向于在主体中使用赋值,因为有更多的空间用来格式化和添加注释,你可以写出这样的语句:
  x=y=z=0;
  memset(this,0,sizeof(this));
  注意第二个片断绝对是非面向对象的。
  当我考虑初始化列表的问题时,有一个奇怪的特性我应该警告你,它是关于C++初始化类成员的,它们是按照声明的顺序初始化的,而不是按照出现在初始化列表中的顺序。
  class CMyClass {
  CMyClass(int x, int y);
  int m_x;
  int m_y;
  CMyClass::CMyClass(int i) : m_y(i), m_x(m_y)
  你可能以为上面的代码将会首先做m_y=i,然后做m_x=m_y,最后它们有相同的值。但是编译器先初始化m_x,然后是m_y,,因为它们是按这样的顺序声明的。结果是m_x将有一个不可预测的值。这个例子是故意这样设计来说明这一点的,然而这种bug会很自然地出现。有两种方法避免它,一个是总是按照你希望它们被初始化的顺序来声明成员,第二个是,如果你决定使用初始化列表,总是按照它们声明的顺序罗列这些成员。这将有助于消除混淆。
相关文章:
[ 责任编辑:之极 ] &&&&
软件信息化周刊
比特软件信息化周刊提供以数据库、操作系统和管理软件为重点的全面软件信息化产业热点、应用方案推荐、实用技巧分享等。以最新的软件资讯,最新的软件技巧,最新的软件与服务业内动态来为IT用户找到软捷径。
商务办公周刊
比特商务周刊是一个及行业资讯、深度分析、企业导购等为一体的综合性周刊。其中,与中国计量科学研究院合力打造的比特实验室可以为商业用户提供最权威的采购指南。是企业用户不可缺少的智选周刊!
比特网络周刊向企业网管员以及网络技术和产品使用者提供关于网络产业动态、技术热点、组网、建网、网络管理、网络运维等最新技术和实用技巧,帮助网管答疑解惑,成为网管好帮手。
服务器周刊
比特服务器周刊作为比特网的重点频道之一,主要关注x86服务器,RISC架构服务器以及高性能计算机行业的产品及发展动态。通过最独到的编辑观点和业界动态分析,让您第一时间了解服务器行业的趋势。
比特存储周刊长期以来,为读者提供企业存储领域高质量的原创内容,及时、全面的资讯、技术、方案以及案例文章,力求成为业界领先的存储媒体。比特存储周刊始终致力于用户的企业信息化建设、存储业务、数据保护与容灾构建以及数据管理部署等方面服务。
比特安全周刊通过专业的信息安全内容建设,为企业级用户打造最具商业价值的信息沟通平台,并为安全厂商提供多层面、多维度的媒体宣传手段。与其他同类网站信息安全内容相比,比特安全周刊运作模式更加独立,对信息安全界的动态新闻更新更快。
新闻中心热点推荐
新闻中心以独特视角精选一周内最具影响力的行业重大事件或圈内精彩故事,为企业级用户打造重点突出,可读性强,商业价值高的信息共享平台;同时为互联网、IT业界及通信厂商提供一条精准快捷,渗透力强,覆盖面广的媒体传播途径。
云计算周刊
比特云计算周刊关注云计算产业热点技术应用与趋势发展,全方位报道云计算领域最新动态。为用户与企业架设起沟通交流平台。包括IaaS、PaaS、SaaS各种不同的服务类型以及相关的安全与管理内容介绍。
CIO俱乐部周刊
比特CIO俱乐部周刊以大量高端CIO沙龙或专题研讨会以及对明星CIO的深入采访为依托,汇聚中国500强CIO的集体智慧。旨为中国杰出的CIO提供一个良好的互融互通 、促进交流的平台,并持续提供丰富的资讯和服务,探讨信息化建设,推动中国信息化发展引领CIO未来职业发展。
IT专家新闻邮件长期以来,以定向、分众、整合的商业模式,为企业IT专业人士以及IT系统采购决策者提供高质量的原创内容,包括IT新闻、评论、专家答疑、技巧和白皮书。此外,IT专家网还为读者提供包括咨询、社区、论坛、线下会议、读者沙龙等多种服务。
X周刊是一份IT人的技术娱乐周刊,给用户实时传递I最新T资讯、IT段子、技术技巧、畅销书籍,同时用户还能参与我们推荐的互动游戏,给广大的IT技术人士忙碌工作之余带来轻松休闲一刻。
微信扫一扫
关注ChinabyteC++初始化列表问题,类中有一个对象类型的数组成员变量,在初始化列表中初始化时报错“[]”操作符语法错误
C++初始化列表问题,类中有一个对象类型的数组成员变量,在初始化列表中初始化时报错“[]”操作符语法错误
class ClassA{private ClassB arrayOfObjectClassB[2];public ClassA(int i):arrayObjectOfClassB[0](i),arrayObjectOfClassB[1](i)}arrayObjectOfClassB[0](i)这儿有问题
数组作为成员变量时只有默认初始化,也就是无法传递参数。有两种变通方案:你可以把对象数组改成指针数组,或者把ClassB类的构造和初始化分开。方案一:class ClassA{private: ClassB* arrayOfObjectClassB[2];public: ClassA(int i){ arrayObjectOfClassB[0]=new ClassB(i); arrayObjectOfClassB[1]=new ClassB(i); }};方案二:class ClassB{private:public: ClassB(int d):data(d){ } ClassB(){ } void Init(int d){data=d;}};class ClassA{private: ClassB arrayOfObjectClassB[2];public: ClassA(int i){ arrayObjectOfClassB[0].Init(i); arrayObjectOfClassB[1].Init(i); }};
等待您来回答
编程领域专家新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
空间积分0 信誉积分311 UID584589阅读权限30积分1272帖子精华可用积分1272 专家积分0 在线时间1944 小时注册时间最后登录
家境小康, 积分 1272, 距离下一级还需 728 积分
帖子主题精华可用积分1272 专家积分0 在线时间1944 小时注册时间最后登录
论坛徽章:0
我看一些C的代碼範例對數組初始化
例如: 要把 a 陣列清成 0
int a[10000];
for ( i = 0; i & 10000; i++ )
int a[10000] = {0}; // 直接初始化
這兩個作法哪個效率比較高????
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp
空间积分0 信誉积分124 UID阅读权限20积分607帖子精华可用积分607 专家积分0 在线时间17 小时注册时间最后登录
丰衣足食, 积分 607, 距离下一级还需 393 积分
帖子主题精华可用积分607 专家积分0 在线时间17 小时注册时间最后登录
论坛徽章:0
前者每次都得比较看是否结束,所以慢,但这个数量级也慢不了太多
空间积分0 信誉积分231 UID7403675阅读权限20积分481帖子精华可用积分481 专家积分0 在线时间205 小时注册时间最后登录
稍有积蓄, 积分 481, 距离下一级还需 19 积分
帖子主题精华可用积分481 专家积分0 在线时间205 小时注册时间最后登录
论坛徽章:0
memset呢?
空间积分0 信誉积分126 UID阅读权限10积分174帖子精华可用积分174 专家积分0 在线时间3 小时注册时间最后登录
白手起家, 积分 174, 距离下一级还需 26 积分
帖子主题精华可用积分174 专家积分0 在线时间3 小时注册时间最后登录
论坛徽章:0
int a[10000] = {0}; // 直接初始化
这种方法只能初始化a[0].
空间积分0 信誉积分124 UID阅读权限20积分607帖子精华可用积分607 专家积分0 在线时间17 小时注册时间最后登录
丰衣足食, 积分 607, 距离下一级还需 393 积分
帖子主题精华可用积分607 专家积分0 在线时间17 小时注册时间最后登录
论坛徽章:0
原帖由 jiazhengw 于
16:57 发表
int a[10000] = {0}; // 直接初始化
这种方法只能初始化a[0].
不知道你用哪个编译器?
gcc下,即使是02优化后
& & 会每次判断一下,再将相应的内存置0
& & 用个计数器,然后再重复置0,指令相对要少一些
虽然后者效率高,但10000这个数量级对cpu影响不会太大
空间积分0 信誉积分126 UID阅读权限10积分174帖子精华可用积分174 专家积分0 在线时间3 小时注册时间最后登录
白手起家, 积分 174, 距离下一级还需 26 积分
帖子主题精华可用积分174 专家积分0 在线时间3 小时注册时间最后登录
论坛徽章:0
我用的是FC5的GCC的呀!我还试过了,如果改为:
int a[10000] = {1};
这样的话也只是a[0] = 1,而其他的都不是1.
不知道你用的是什么编译器。
空间积分0 信誉积分116 UID587665阅读权限100积分6907帖子精华可用积分6909 专家积分20 在线时间1377 小时注册时间最后登录
帖子主题精华可用积分6909 专家积分20 在线时间1377 小时注册时间最后登录
论坛徽章:0
int a[10000] = {0};&&就可以了
要么就:&&memset(a, 0, sizeof(int) * 10000);
8年女程序员:“低头做事,抬头做人,过幸福小日子”
空间积分0 信誉积分192 UID650426阅读权限20积分946帖子精华可用积分946 专家积分6 在线时间907 小时注册时间最后登录
丰衣足食, 积分 946, 距离下一级还需 54 积分
帖子主题精华可用积分946 专家积分6 在线时间907 小时注册时间最后登录
论坛徽章:0
公司常用VC, VC的编译器:
char a[100] = {0}; 会把所有的都初始化为0
感觉还是推荐memset()
Traveling light
空间积分0 信誉积分100 UID7605624阅读权限20积分665帖子精华可用积分665 专家积分0 在线时间222 小时注册时间最后登录
丰衣足食, 积分 665, 距离下一级还需 335 积分
帖子主题精华可用积分665 专家积分0 在线时间222 小时注册时间最后登录
论坛徽章:0
原帖由 jiazhengw 于
18:18 发表
我用的是FC5的GCC的呀!我还试过了,如果改为:
int a[10000] = {1};
这样的话也只是a[0] = 1,而其他的都不是1.
不知道你用的是什么编译器。
非0的值当然拉。但是如果是0的话,那就全部默认是0了。
空间积分0 信誉积分311 UID584589阅读权限30积分1272帖子精华可用积分1272 专家积分0 在线时间1944 小时注册时间最后登录
家境小康, 积分 1272, 距离下一级还需 728 积分
帖子主题精华可用积分1272 专家积分0 在线时间1944 小时注册时间最后登录
论坛徽章:0
我刚试了一下用memset()函式
#include &stdio.h&
#include &stdlib.h&
int main()
& & int a[100];& &
& & memset(a, 1, sizeof(a));
& & for ( i = 0; i & 100; i++)
& && &&&printf(&%d ,&,a[i]);
& & system(&pause&);
memset(a, 0, sizeof(a));&&都是 0 正确
memset(a, 1, sizeof(a));
想把 int a [100]; // 0~99 值都变成 1
不过出来的值是 怎么不是 1??????
北京皓辰网域网络信息技术有限公司. 版权所有 京ICP证:060528号 北京市公安局海淀分局网监中心备案编号:
广播电视节目制作经营许可证(京) 字第1234号
中国互联网协会会员&&联系我们:
感谢所有关心和支持过ChinaUnix的朋友们
转载本站内容请注明原作者名及出处疑问: c++程序 对象初始化的问题
[问题点数:20分,结帖人kong]
疑问: c++程序 对象初始化的问题
[问题点数:20分,结帖人kong]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
2007年6月 总版技术专家分月排行榜第三
2007年6月 VC/MFC大版内专家分月排行榜第一
本帖子已过去太久远了,不再提供回复功能。}

我要回帖

更多关于 初始化随机数发生器 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信