2010-06-21 105 views
1

请告诉我,从C++开始执行的地方,希望你的答案是“从主要的”。开始执行

那该怎么办?

class abc 
{ 
public: 
    abc() 
    { 
     cout<<"hello"; 
    } 
}; 

const abc obj; 

int main() 
{ 
    cout<<"Main"; 
} 

输出:

helloMain 

请详细说明。

+1

我想你需要考虑你的意思是“哪里开始执行”什么,因为刚关于每个编译语言都会有一些代码在您编写的第一条语句之前运行。 – 2010-06-21 11:33:19

回答

4

从您的意见到其他答案支柱,这听起来像一个10,000英尺的视图可能有助于理解。

启动应用程序所涉及的确切步骤在操作系统,编译器和编程语言中各不相同,但“一般”过程基本相同。

  1. OS内核被要求开始运行目标可执行
  2. 内核创建一个新的进程来承载exectuable
  3. 内核建立了基本的进程属性的新工艺:文件描述符,环境变量,安全属性等。
  4. 内核运行用户模式的“加载程序”,以实际打开连接可执行文件的文件并准备好执行
  5. 加载程序读取包含可执行文件的文件并将其分解为各种段:全局变量数据,可执行代码等
  6. 加载程序解析任何动态链接库符号并正确地为可执行代码布置内存(实质上,这一步涉及确保程序中的所有指针指向正确的位置)
  7. 然后loder调用可执行文件的“入口”功能。但是,这不是你的'主要'功能。 '入口'函数通常被操作系统/编译器隐藏,以允许运行主前置初始化代码。
  8. 在C++的输入功能的情况下,将最有可能看起来像以下:

int __entry(int argc, char *argv[]) 
{ 
    // configure standard I/O streams, threading tables, & other utilities 
    initialize_c_runtime(); 

    // run the constructors for all static objects 
    initialize_static_cplusplus_objects(); 

    // Now, finally, after *all* that we execute the 'main' function 
    return main(argc, argv); 
} 
+1

谢谢:) 非常有帮助。 – Sadique 2010-06-22 13:11:49

12

调用main之前,会创建全局变量(并因此调用其构造函数)。


答到OP的评论:

如果你想挖比你写的代码更深入的,有事情main之前发生的事情被调用,而我自己也没有一个清晰的画面。我正在谈论我们编写的代码 - 入口点是main函数,在初始化全局变量后调用该函数。碰巧,类实例的初始化意味着调用它的构造函数。

因此简而言之,行const abc obj;创建一个abc类型的全局变量,它在调用main之前被初始化(它是调用print语句的默认构造函数)。因此,输出helloMain

+0

@strut请参阅更新 – Amarghosh 2010-06-21 13:09:32

3

您声明obj作为类abc的常量变量。变量obj在程序开始执行之前由编译器提供的代码分配一个默认值。此代码调用默认构造函数以创建abc类型的默认对象,并将其指定给obj

抛开静态初始化,说从main()开始执行是正确的。

0

由于obj是一个全局对象,它将在main执行之前实例化。它就像任何其他全局变量一样,即当你将整型变量声明为全局变量时,它包含0,而不是任何垃圾值。因此,您的对象正在实例化,并调用构造函数,然后打印hello字符串。

0

应用程序不从main启动。以下是从主开始有些堆栈快照(对于一个控制台应用程序,Unicode版本),用VS2005编译:

MyApp.exe的wmain(INT ARGC = 00000001,为wchar_t * argv的= 0x00364d68)线! 67 C++

myapp.exe!__tmainCRTStartup() Line 594 + 0x17 bytes  

[email protected]() + 0x23 bytes  

第一功能,可以说以在用户模式中的新进程上下文中运行是BaseProcessStart,这是一个Win32电平函数。它调用CRT级mainCRTStartup,它使用二进制映像本身中的各种数据段来运行各种初始化程序 - 例如全局构造函数,如obj。事实上,你可以在你的ctor中设置一个断点并自己看:

myapp。exe文件!`动态初始化for'obj ''()

MSVCR80.DLL!_initterm(...)

MyApp.exe的!__ tmainCRTStartup()

[email protected]()

(在那里有一些格式化的困难)。 initterm是对全局对象进行迭代并调用其构造函数的函数。

在不同的平台和编译器上(甚至在VS上,MFC应用程序非常不同),堆栈看起来不同,但这个想法总是相同的:运行时使用二进制映像信息初始化全局对象主要进入。

+0

请注意,您将以非标准模式显示VC++(使用'wmain()',但这并不完全有效,但是当调用入口点时,将使用调用全局变量的ctors的相同隐藏函数是标准的'int main(int argc,char ** argv)' – MSalters 2010-06-21 11:39:19

+0

我明确地注意到它是一个unicode版本。什么不是完全有效的? – 2010-06-21 11:43:54

+0

这是问题!现在你真的认为我有任何线索你说什么先生Shilon !! 重申我对你的解释无能为力! – Sadique 2010-06-21 12:34:41