比如有一个人为的例子:...
int main() {
/*
некоторый код
*/
...{
static int someVal = 42;
}
}
什么时候创建变量?在程序启动期间或当我们得到正确的指令时?
比如有一个人为的例子:...
int main() {
/*
некоторый код
*/
...{
static int someVal = 42;
}
}
什么时候创建变量?在程序启动期间或当我们得到正确的指令时?
这个问题没有明确的答案,因为在一般情况下,答案主要取决于对象的类型。在您使用类型的特定示例中
int
- 对象始终严格在程序启动时创建。一般来说,这取决于你所谓的“创造”。
C++ 中的对象具有“存储持续时间”和“生命周期”。
存储期是对象占用的“原始”内存的分配-释放期。
任何静态对象的存储周期总是无条件的就是整个程序的执行时间。
生命周期是该原始内存中对象的 [非平凡] 初始化和 [非平凡] 销毁之间的时间段。生存期总是嵌套在存储期中。生命周期取决于对象的属性。
如果对象的初始化是平凡的(即,如果它是非类类型或使用平凡默认构造函数初始化的类类型),则根本不需要构造,并且存储期的开始自动成为一生。
类似地,如果对象的销毁是微不足道的(即,如果它是非类类型或具有微不足道析构函数的类类型),则生命周期将持续到存储期结束。
如果一个静态对象需要一个非平凡的构造,那么它将在对象声明的执行过程的第一遍时执行(如果这样的时刻到来的话)。
此外,如果标量类型(例如 type
int
)的对象使用常量表达式进行初始化,则此类初始化将静态执行(在程序开始时)。如果表达式是非常量,在程序开始时,这样的对象将被初始化为零,表达式的初始化将在稍后动态地执行。对于本地声明的对象,这将在第一次通过对象声明时发生(如果有的话)。在您的情况下,您正在处理 type 的静态对象
int
。这样一个对象的存储周期就是程序执行的整个持续时间。并且由于它是非类类型,因此该对象的生命周期就是程序的整个持续时间。此外,该语言向您保证该对象的初始化是静态完成的——不是在该对象声明的第一次执行过程中,而是在程序开始时立即完成。比如下面的代码保证输出
42
但这款保证能带来
0
如果换成
int
,std::string
那么这样一个对象的存储周期仍然是整个程序的执行时间。但是这个对象的生命周期将在第一次执行通过它的声明时开始(如果这样的时刻到来的话)。例如,这里是代码
会看到对象
s
,已经被无差别零初始化的滚轮传过去了,但是还没有执行构造。对象的生命周期尚未开始。行为未定义。第一次执行代码。
例如,您可以通过使用构造函数创建某个类的变量来确保。
得到
如果不是构造函数调用,变量的创建是什么?:)
更新
那么,让我们澄清一下——什么是变量的创建?分配的内存空间是否可以视为变量的创建?不太可能,因为一般情况下它只是内存中的一个地方,只有把内存中的这个地方当成这个类型的变量,它才会成为某个类型的变量。
最有可能 - 虽然这不是编译器所必需的!-将在编译阶段为此类变量分配一个位置。
int
对于像,double
or -这样的简单类型,char[]
内存很可能会立即被适当填充。但这并不意味着创建一个变量。作为一个变量,这块内存会在第一次被访问的时候,第一次进入作用域的时候被对待。如果这比 simple 更复杂int
,那么第一个调用将是调用构造函数。如果不是,则不会调用构造函数,但是,无论类型如何,变量只会在现在出现!因为没有人禁止——没有标准——在函数第一次执行时为这个变量分配动态内存给编译器。真正的编译器这样做的方式与创建变量的问题无关。
我希望我或多或少地表达了我的观点。
让我再次提醒你——编译器有很大的权利来改变程序——只要它能像编写的那样工作。
我怀疑这取决于进一步的代码和/或编译器设置。这样的例子
给出以下输出代码:
也就是说,没有这样的变量,编译器将其优化为常量。这是代码:
导致创建一个在编译时初始化的全局变量。
奇怪的是,这么简单的问题居然没有人给出直接正常的回答。很多关于生命周期和某种“原始”记忆的推理。甚至有点伤感。事实上,最后一个答案最接近正确,但不知何故不确定。
最终,答案是:
所有不需要构造的全局变量和静态变量都是在编译时创建和初始化的。并且,通常,它们存储在数据段中,或者如果不从其他地方访问它们,则直接在代码段中将它们优化为常量。
通常,所有不需要
构造的局部变量或动态变量都在
其本地化堆栈中创建和初始化。那些。函数内部的变量是在
该函数的堆栈上创建的。此类变量在进入函数或块时创建,并在程序执行期间退出时销毁。
所有需要构造的变量(对象)都
在程序执行期间相应地构造。程序启动时为全局,在
本地化位置创建后为本地。
现在,关于这个问题
变量someVal将在编译时创建和初始化。如果没有对它的调用,那么它将完全平整为常量甚至删除。如果它被访问,那么它很可能会被放在数据段中。在编译时,只能从其块内访问此变量。并且由于在这种特殊情况下没有调用它,所以它会被简单地删除,甚至不会进入程序代码。