RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 648385
Accepted
user241373
user241373
Asked:2020-04-04 23:48:17 +0000 UTC2020-04-04 23:48:17 +0000 UTC 2020-04-04 23:48:17 +0000 UTC

变量创建时间

  • 772

比如有一个人为的例子:...

int main() {
    /*
        некоторый код
    */
    ...{
        static int someVal = 42;
    }
}

什么时候创建变量?在程序启动期间或当我们得到正确的指令时?

c++
  • 4 4 个回答
  • 10 Views

4 个回答

  • Voted
  1. Best Answer
    AnT stands with Russia
    2020-04-05T01:55:57Z2020-04-05T01:55:57Z

    这个问题没有明确的答案,因为在一般情况下,答案主要取决于对象的类型。在您使用类型的特定示例中int- 对象始终严格在程序启动时创建。

    一般来说,这取决于你所谓的“创造”。

    C++ 中的对象具有“存储持续时间”和“生命周期”。

    • 存储期是对象占用的“原始”内存的分配-释放期。

      任何静态对象的存储周期总是无条件的就是整个程序的执行时间。

    • 生命周期是该原始内存中对象的 [非平凡] 初始化和 [非平凡] 销毁之间的时间段。生存期总是嵌套在存储期中。生命周期取决于对象的属性。

      如果对象的初始化是平凡的(即,如果它是非类类型或使用平凡默认构造函数初始化的类类型),则根本不需要构造,并且存储期的开始自动成为一生。

      类似地,如果对象的销毁是微不足道的(即,如果它是非类类型或具有微不足道析构函数的类类型),则生命周期将持续到存储期结束。

      如果一个静态对象需要一个非平凡的构造,那么它将在对象声明的执行过程的第一遍时执行(如果这样的时刻到来的话)。

    此外,如果标量类型(例如 type int)的对象使用常量表达式进行初始化,则此类初始化将静态执行(在程序开始时)。如果表达式是非常量,在程序开始时,这样的对象将被初始化为零,表达式的初始化将在稍后动态地执行。对于本地声明的对象,这将在第一次通过对象声明时发生(如果有的话)。

    在您的情况下,您正在处理 type 的静态对象int。这样一个对象的存储周期就是程序执行的整个持续时间。并且由于它是非类类型,因此该对象的生命周期就是程序的整个持续时间。此外,该语言向您保证该对象的初始化是静态完成的——不是在该对象声明的第一次执行过程中,而是在程序开始时立即完成。

    比如下面的代码保证输出42

    // Продолжительность хранения `i` уже началась
    // Время жизни `i` уже началось
    // `i` уже проинициализировано значением 42
    int main()
    {
    goto skip;    
      static int i = 42; // Статическая инициализация
    skip:
      std::cout << i << std::endl;
    }
    

    但这款保证能带来0

    // Продолжительность хранения `i` уже началась
    // Время жизни `i` уже началось
    // `i` уже проинициализировано значением 0
    int main()
    {
    goto skip;    
      static int i = std::rand(); // Динамическая инициализация
    skip:
      std::cout << i << std::endl;
    }
    

    如果换成int,std::string那么这样一个对象的存储周期仍然是整个程序的执行时间。但是这个对象的生命周期将在第一次执行通过它的声明时开始(如果这样的时刻到来的话)。

    例如,这里是代码

    // Продолжительность хранения `s` уже началась
    // Время жизни `s` еще не началось
    // Однако все члены `s` уже проинициализированы нулями
    int main()
    {
    goto skip;    
      static std::string s = "Hello World!"; // Динамическая инициализация и начало жизни
    skip:
      std::cout << s << std::endl;
    }
    

    会看到对象s,已经被无差别零初始化的滚轮传过去了,但是还没有执行构造。对象的生命周期尚未开始。行为未定义。

    • 27
  2. Harry
    2020-04-04T23:51:09Z2020-04-04T23:51:09Z

    第一次执行代码。

    例如,您可以通过使用构造函数创建某个类的变量来确保。

    struct Test
    {
        Test(int x) { cout << x << endl; }
    };
    
    
    int main()
    {
        for(int i = 0; i < 10; ++i)
        {
            cout << i << endl;
            static Test t = 42;
        }
    }
    

    得到

    0
    42
    1
    2
    3
    4
    5
    6
    7
    8
    9
    

    如果不是构造函数调用,变量的创建是什么?:)

    更新

    那么,让我们澄清一下——什么是变量的创建?分配的内存空间是否可以视为变量的创建?不太可能,因为一般情况下它只是内存中的一个地方,只有把内存中的这个地方当成这个类型的变量,它才会成为某个类型的变量。

    最有可能 - 虽然这不是编译器所必需的!-将在编译阶段为此类变量分配一个位置。int对于像, doubleor -这样的简单类型,char[]内存很可能会立即被适当填充。但这并不意味着创建一个变量。作为一个变量,这块内存会在第一次被访问的时候,第一次进入作用域的时候被对待。如果这比 simple 更复杂int,那么第一个调用将是调用构造函数。如果不是,则不会调用构造函数,但是,无论类型如何,变量只会在现在出现!

    因为没有人禁止——没有标准——在函数第一次执行时为这个变量分配动态内存给编译器。真正的编译器这样做的方式与创建变量的问题无关。

    我希望我或多或少地表达了我的观点。

    让我再次提醒你——编译器有很大的权利来改变程序——只要它能像编写的那样工作。

    • 12
  3. Владимир Мартьянов
    2020-04-04T23:56:09Z2020-04-04T23:56:09Z

    我怀疑这取决于进一步的代码和/或编译器设置。这样的例子

    static int someVal = 42;
    printf ("0x%X", someVal);
    

    给出以下输出代码:

    .text:0040101E                 push    42
    .text:00401020                 push    offset Format   ; "0x%X"
    .text:00401025                 call    esi ; __imp__printf
    

    也就是说,没有这样的变量,编译器将其优化为常量。这是代码:

    printf ("0x%X", someVal);
    someVal++;
    printf ("0x%X", someVal);
    

    导致创建一个在编译时初始化的全局变量。

    • 7
  4. Andrey Sv
    2020-11-04T06:26:27Z2020-11-04T06:26:27Z

    奇怪的是,这么简单的问题居然没有人给出直接正常的回答。很多关于生命周期和某种“原始”记忆的推理。甚至有点伤感。事实上,最后一个答案最接近正确,但不知何故不确定。

    最终,答案是:

    • 所有不需要构造的全局变量和静态变量都是在编译时创建和初始化的。并且,通常,它们存储在数据段中,或者如果不从其他地方访问它们,则直接在代码段中将它们优化为常量。

    • 通常,所有不需要
      构造的局部变量或动态变量都在
      其本地化堆栈中创建和初始化。那些。函数内部的变量是在
      该函数的堆栈上创建的。此类变量在进入函数或块时创建,并在程序执行期间退出时销毁。

    • 所有需要构造的变量(对象)都
      在程序执行期间相应地构造。程序启动时为全局,在
      本地化位置创建后为本地。


    现在,关于这个问题

    int main() {
        /*
            некоторый код
        */
        ...{
            static int someVal = 42;
        }
    }
    

    变量someVal将在编译时创建和初始化。如果没有对它的调用,那么它将完全平整为常量甚至删除。如果它被访问,那么它很可能会被放在数据段中。在编译时,只能从其块内访问此变量。并且由于在这种特殊情况下没有调用它,所以它会被简单地删除,甚至不会进入程序代码。

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5