C++03标准阅读笔记-3.6 Start and termination

3.6 Start and termination 启动和结束
3.6.1 Main函数
1 A program shall contain a global function called main, which is the designated start of the program.

一个程序必须包含一个全局main函数,它将作为程序的入口。

It is implementation-defined whether a program in a freestanding environment is required to define a main
function.

在独立的环境中,程序是否需要定义main函数由实现决定。实现在这里及下面都是指编译器。

[Note: in a freestanding environment, start-up and termination is implementation-defined; startup contains the execution of constructors for objects of namespace scope with static storage duration; termination contains the execution of destructors for objects with static storage duration. ]
2 An implementation shall not predefine the main function. This function shall not be overloaded.

实现不能预定义main函数,并且该函数不能重载。

It shall have a return type of type int, but otherwise its type is implementation-defined.

main函数必须返回int类型,但其它方面(如参数)可以由实现定义。

如可以定义成这样:int main(int argc, char* argv[], char *envp[])

All implementations shall allow both of the following definitions of main:

所有实现必须允许以下两种格式main定义:
int main() { /* ... */ }

int main(int argc, char* argv[]) { /* ... */ }
In the latter form argc shall be the number of arguments passed to the program from the environment in
which the program is run.

后面的格式的argc参数必须是由程序运行环境传给程序的参数个数值。

If argc is nonzero these arguments shall be supplied in argv[0] through argv[argc-1] as pointers to the initial characters of null-terminated multibyte strings (NTMBSs)
(17.3.2.1.3.2) and argv[0] shall be the pointer to the initial character of a NTMBS that represents the
name used to invoke the program or "".

如果argc为非0值,则参数argv[0]到argv[argc-1]必须指向非空多字节结尾的初始化字符串;argv[0]为调用程序的名称或空。

The value of argc shall be nonnegative. The value of argv[argc] shall be 0. [Note: it is recommended that any further (optional) parameters be added after argv. ]

argc不能为负数,argv[argc]的值为0。[注意:建议任何附加的参数(可选)加到argv参数后面]

3 The function main shall not be used (3.2) within a program.

在程序中不能调用main函数。在VS2015下运行将会导致栈溢出。

The linkage (3.5) of main is implementation-defined.

main函数的链接是由实现定义。意思编译器提供main原型。

A program that declares main to be inline or static is ill-formed.

不能声明main函数为内联或静态函数。

The name main is not otherwise reserved. [Example: member functions, classes, and enumerations can be
called main, as can entities in other namespaces. ]

名称main不是保留字。
4 Calling the function void exit(int); declared in <cstdlib> (18.3) terminates the program without leaving the current block and hence without destroying any objects with automatic storage duration (12.4).

exit(int)函数声明在<stdlib>库中,调用时直接跳过当前块终止程序,因些任何自动化存储周期对象都不会释放。

If exit is called to end a program during the destruction of an object with static storage duration, the program has undefined behavior.

如果在一个静态存储周期对象的析构中调用exit,那程序将处于未定义行为,即结果不可预测
5 A return statement in main has the effect of leaving the main function (destroying any objects with automatic storage duration) and calling exit with the return value as the argument.

return起到离开main函数的作用(并且释放任何自动化存储周期对象),并且调用exit,参数为return中指定的值。

If control reaches the end of main without encountering a return statement, the effect is that of executing return 0;

如果运行到main的最后没有return语句,那相当于执行return 0。

例下面程序

int main() {}

g++ main.cpp && ./a.out && echo $?

返回0

3.6.2 Initialization of non-local objects 非本地变量的初始化
1 Objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initialization takes place.
静态存储持续性的对象必须在其它初始化之前完成零初始化。 
Zero-initialization and initialization with a constant expression are collectively called static initialization; all other initialization is dynamic initialization. 
零初始化和使用常量表达式初始化都称为静态初始化,其它的都为动态初努化。静态初始化即在编译时就能确认它的值的初始化。常量表达式包括字面常量,const和enum常量,以及sizeof操作符。
Objects of POD types (3.9) with static storage duration initialized with constant expressions (5.19) shall be initialized before any dynamic initialization takes place. 
静态存储周期的POD(纯旧数据)类型对象通过常量初始化必须在其它动态初始化之前完成。
Objects with static storage duration defined in namespace scope in the same translation unit and dynamically initialized shall be initialized in the order in which their definition appears in the translation unit. 
同一编译单元的命名空间内的静态存储r持续性定义和动态初始化的对象,必须按它们在编译单元内出现的顺序进行初始化。
[Note: 8.5.1 describes the order in which aggregate members are initialized. The initialization of local static objects is described in 6.7. ]
2 An implementation is permitted to perform the initialization of an object of namespace scope with static storage duration as a static initialization even if such initialization is not required to be done statically, provided that
对于命名空间内静态存储持续性的对象就算不需要进行静态初始化,但实现也可以当作静态初始化处理,前提是:
— the dynamic version of the initialization does not change the value of any other object of namespace scope with static storage duration prior to its initialization, and
-在它进行动态初始化之前,不会改变任何命名空间内静态存储持续性的其它对象值,以及
— the static version of the initialization produces the same value in the initialized object as would be produced by the dynamic initialization if all objects not required to be initialized statically were initialized dynamically.
-如果所有不需要静态初始化的对象都是动态初始化,并且静态初始化与将要动态初始化的结果一样。

[Note: as a consequence, if the initialization of an object obj1 refers to an object obj2 of namespace scope with static storage duration potentially requiring dynamic initialization and defined later in the same translation unit, it is unspecified whether the value of obj2 used will be the value of the fully initialized obj2 (because obj2 was statically initialized) or will be the value of obj2 merely zero-initialized. For example,
因些,如果命名空间内静态存储对象obj1的初始化引用的对象obj2,并且obj1可能需要动态初始化,并且在同一编译单元后面定义,那obj2是未定义,可能obj2将使用完整初始化的值(因为obj2是静态初始化),或者只是作零初始化。例子:

inline double fd() { return 1.0; }
extern double d1;
double d2 = d1; // unspecified: 未指定
                // may be statically initialized to 0.0 or 可能静态初始化为0.0,或
                // dynamically initialized to 1.0 动态初始化1.0
double d1 = fd(); // may be initialized statically to 1.0 可能静态初始化为1.0
—end note]

3 It is implementation-defined whether or not the dynamic initialization (8.5, 9.4, 12.1, 12.6.1) of an object of namespace scope is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first use of any function or object defined in the same translation unit as the object to be initialized.31) [Example:
实现定义(即编译器)决定是否在main的第一条语句之前进行对象动态初始化。如果初始化被推迟到main第一条语句后的某个时间点进行,则在同一编译单元中被任何函数或对象定义使用前必须初始化。例子:
// – File 1 –
#include "a.h"
#include "b.h"
B b;
A::A(){
b.Use();
}
// – File 2 –
#include "a.h"
A a;
// – File 3 –
#include "a.h"
#include "b.h"
extern A a;
extern B b;
int main() {
a.Use();
b.Use();
}
It is implementation-defined whether either a or b is initialized before main is entered or whether the initializations are delayed until a is first used in main. 
由实现定义决定a或b是在进入main之前或直到执行main中的第一条语句时进行初始化。
In particular, if a is initialized before main is entered, it is not guaranteed that b will be initialized before it is used by the initialization of a, that is, before A::A is called. 
特别是,如果a是在进入main之前初始化,在调用A:A进行a初始化时不能保证b已经被初始化。
If, however, a is initialized at some point after the first statement of main, b will be initialized prior to its use in A::A. ]
如果a在main第1个语句之后的某个时间点进行初始化,将在A::A中之前完成b的初始化。

4 If construction or destruction of a non-local static object ends in throwing an uncaught exception, the result is to call terminate (18.6.3.3).
如果在非本地静态对象构造或析构抛出一个未捕抓的异常,结果将调用terminate。

3.6.3 Termination 终止
1 Destructors (12.4) for initialized objects of static storage duration (declared at block scope or at namespace scope) are called as a result of returning from main and as a result of calling exit (18.3). 
从main函数返回或调用exit函数,将释放初始化的静态存储周期对象。
下面代码将只执行Test1对象的析构函数。
{
    static CTest Test1;
    CTest Test2;
    exit(1);
}

These objects are destroyed in the reverse order of the completion of their constructor or of the completion of their dynamic initialization. 
对象的释放与它们完成构造或动态初始化的顺序相反。

If an object is initialized statically, the object is destroyed in the same order as if the object was dynamically initialized. 
如果对象是静态初始化的,则它的释放顺序的规则与它按动态初始化的顺序相同。 

For an object of array or class type, all subobjects of that object are destroyed before any local object with static storage duration initialized during the construction of the subobjects is destroyed.
对于数据和类对象,在任何本地静态周期对象初始化期间构造的子对象销毁之前,它们的所有子对象都将销毁掉。

2 If a function contains a local object of static storage duration that has been destroyed and the function is called during the destruction of an object with static storage duration, the program has undefined behavior if the flow of control passes through the definition of the previously destroyed local object.
如果函数包含一个静态存储周期的本地对象,并且对象在析构过程中调用了该函数,那函数将处于未定义的行为,如果控制流程跳过前面销毁的本地对象。

3 If a function is registered with atexit (see <cstdlib>, 18.3) then following the call to exit, any objects with static storage duration initialized prior to the registration of that function shall not be destroyed until the registered function is called from the termination process and has completed. 
如果函数注册到atexit,那在调用exit后调用这些函数,任何在注册前初始化的静态存储周期对象,必须在调用注册函数完成后才能销毁。

For an object with static storage duration constructed after a function is registered with atexit, then following the call to exit, the registered function is not called until the execution of the object’s destructor has completed. 
在调用atexit函数注册后构造的静态存储周期对象,当调用exit时,必须在对象的析构完成后才调用注册的函数。

If atexit is called during the construction of an object, the complete object to which it belongs shall be destroyed before the registered function is called.
如果atexit函数是在对象的构造过程中调用的,则必须完成对象析构后再调用注册的函数。

4 Calling the function void abort(); declared in <cstdlib> terminates the program without executing destructors for objects of automatic or static storage duration and without calling the functions passed to atexit().
函数void abort()声明在<cstdlib>,调用该函数将终止程序并且自动和静态存储周期对象的析构函数不会被调用,atexit注册的函数也不会被调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值